Menu
Coddy logo textTech

Padrão Abstract Factory

Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 88 de 107.

O padrão Abstract Factory estende o padrão Factory ao criar famílias de objetos relacionados sem especificar seus tipos concretos. Em vez de uma única função de fábrica, você define uma interface de fábrica que várias fábricas concretas implementam, cada uma produzindo um conjunto consistente de objetos relacionados.

Considere um toolkit de UI que precisa criar buttons e checkboxes. Diferentes sistemas operacionais exigem implementações diferentes, mas os componentes devem funcionar juntos de forma consistente:

type Button interface {
    Render() string
}

type Checkbox interface {
    Check() string
}

// Interface de fábrica abstrata
type GUIFactory interface {
    CreateButton() Button
    CreateCheckbox() Checkbox
}

Cada fábrica concreta produz uma família de componentes relacionados:

// Família Windows
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }

type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }

type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }

// Família Mac
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }

type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }

type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }

O código do cliente trabalha com a interface de fábrica, permanecendo independente das implementações concretas:

func BuildUI(factory GUIFactory) {
    button := factory.CreateButton()
    checkbox := factory.CreateCheckbox()
    fmt.Println(button.Render(), checkbox.Check())
}

Use a Fábrica Abstrata quando seu sistema precisar trabalhar com várias famílias de produtos relacionados e você quiser garantir que componentes da mesma família sejam usados em conjunto. Ela é mais complexa do que uma Fábrica simples, portanto recorra a ela somente quando realmente precisar gerenciar famílias de produtos.

challenge icon

Desafio

Fácil

Vamos criar um sistema de loja de móveis usando o padrão Abstract Factory! Você criará fábricas que produzem famílias de itens de mobiliário relacionados: cada fábrica produz um estilo consistente (Modern ou Vintage), garantindo que as cadeiras e mesas da mesma fábrica combinem esteticamente.

Você organizará seu código em três arquivos:

  • furniture.go: defina suas interfaces de produto e os tipos concretos de móveis.

    Crie duas interfaces de produto:

    • Chair com um método SitOn() string
    • Table com um método PlaceItems() string

    Implemente duas famílias de móveis:

    • Família Modern: ModernChair retorna Sitting on a sleek modern chair e ModernTable retorna Placing items on a glass modern table
    • Família Vintage: VintageChair retorna Sitting on an ornate vintage chair e VintageTable retorna Placing items on a wooden vintage table
  • factory.go: defina sua interface de fábrica abstrata e as fábricas concretas.

    Crie uma interface FurnitureFactory com dois métodos:

    • CreateChair() Chair
    • CreateTable() Table

    Implemente duas fábricas concretas:

    • ModernFactory, que produz ModernChair e ModernTable
    • VintageFactory, que produz VintageChair e VintageTable

    Crie também uma função GetFactory(style string) FurnitureFactory que retorna a fábrica apropriada com base no estilo (modern ou vintage). Use ModernFactory como padrão para estilos não reconhecidos.

  • main.go: use suas fábricas para mobiliar cômodos.

    Crie uma função FurnishRoom(factory FurnitureFactory) string que usa a fábrica para criar uma cadeira e uma mesa e, em seguida, retorna uma string formatada mostrando ambas as ações em linhas separadas.

    Leia uma entrada de estilo, obtenha a fábrica apropriada, mobílie um cômodo e imprima o resultado.

As seguintes entradas serão fornecidas:

  • Linha 1: estilo do móvel (modern, vintage ou algo diferente)

Por exemplo, dada a entrada:

modern

Sua saída deve ser:

Sitting on a sleek modern chair
Placing items on a glass modern table

E dada a entrada:

vintage

Sua saída deve ser:

Sitting on an ornate vintage chair
Placing items on a wooden vintage table

E dada a entrada:

rustic

Sua saída deve ser:

Sitting on a sleek modern chair
Placing items on a glass modern table

Observe como a função FurnishRoom funciona com qualquer fábrica por meio da interface. Ela não sabe se está criando móveis modernos ou vintage. Isso garante que todos os móveis de um cômodo venham da mesma família, mantendo um estilo consistente!

Experimente você mesmo

package main

import "fmt"

// FurnishRoom usa uma factory para criar móveis e retorna o resultado
// TODO: Implemente esta função
// - Use a factory para criar uma cadeira e uma mesa
// - Retorne uma string com o resultado de SitOn() na primeira linha e o resultado de PlaceItems() na segunda linha
func FurnishRoom(factory FurnitureFactory) string {
	// TODO: Crie a cadeira e a mesa usando a factory
	// TODO: Retorne a string formatada com ambas as ações em linhas separadas
	return ""
}

func main() {
	var style string
	fmt.Scanln(&style)

	// TODO: Obtenha a factory apropriada com base no style
	// TODO: Mobilie uma sala usando a factory
	// TODO: Imprima o resultado
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de Go online