Abstract Factory
Definição (GoF): “Fornecer uma interface para criar famílias de objetos relacionados (ou dependentes) sem especificar suas classes concretas.”
Problema
- O cliente precisa criar variações compatíveis de objetos (ex.: círculo e retângulo vermelhos ou azuis) e trocar a família inteira em um ponto só.
- Sem Abstract Factory, o código enche de
if/switch e new espalhados, acoplando o cliente a classes concretas e dificultando a troca da família.
classDiagram
direction TD
class Cliente {
- cor: String
+Cliente(String cor)
+desenharCena()
}
class Circulo { +draw():String }
class Retangulo { +draw():String }
class CirculoVermelho
class RetanguloVermelho
class CirculoAzul
class RetanguloAzul
Cliente --> Circulo : usa (new ...)
Cliente --> Retangulo : usa (new ...)
Circulo <|-- CirculoVermelho
Retangulo <|-- RetanguloVermelho
Circulo <|-- CirculoAzul
Retangulo <|-- RetanguloAzul
note for Cliente "if (cor==VERMELHO) new CirculoVermelho(); else new CirculoAzul(); ..."
Código Fonte (Problema — acoplado com if e new)
Solução (GoF)
- Definir uma Abstract Factory com métodos para cada produto da família (
createCirculo(), createRetangulo()).
- Cada Concrete Factory cria uma família compatível (ex.:
VermelhaFactory cria só produtos vermelhos).
- O Cliente recebe a fábrica (injeção) e nunca instancia produtos concretos.
Diagrama GoF Genérico (Mermaid)
classDiagram
direction LR
class Client
class AbstractFactory {
<<interface>>
+createA(): AbstractProductA
+createB(): AbstractProductB
}
class ConcreteFactory1
class ConcreteFactory2
class AbstractProductA { <<interface>> }
class AbstractProductB { <<interface>> }
class ProductA1
class ProductB1
class ProductA2
class ProductB2
Client --> AbstractFactory : usa
AbstractFactory <|.. ConcreteFactory1
AbstractFactory <|.. ConcreteFactory2
AbstractProductA <|.. ProductA1
AbstractProductB <|.. ProductB1
AbstractProductA <|.. ProductA2
AbstractProductB <|.. ProductB2
ConcreteFactory1 --> ProductA1 : cria
ConcreteFactory1 --> ProductB1 : cria
ConcreteFactory2 --> ProductA2 : cria
ConcreteFactory2 --> ProductB2 : cria
Exemplo 1 — Famílias de Figuras coloridas (Círculo/Retângulo)
Diagrama da Solução
classDiagram
direction TD
class Cliente {
-fabrica: ShapeFactory
+Cliente(ShapeFactory f)
+desenharCena()
}
class ShapeFactory {
<<interface>>
+createCirculo(): Circulo
+createRetangulo(): Retangulo
}
class VermelhaFactory
class AzulFactory
class Circulo { <<interface>> +draw():String }
class Retangulo { <<interface>> +draw():String }
class CirculoVermelho
class RetanguloVermelho
class CirculoAzul
class RetanguloAzul
Cliente --> ShapeFactory : usa
ShapeFactory <|.. VermelhaFactory
ShapeFactory <|.. AzulFactory
Circulo <|.. CirculoVermelho
Retangulo <|.. RetanguloVermelho
Circulo <|.. CirculoAzul
Retangulo <|.. RetanguloAzul
VermelhaFactory --> CirculoVermelho : cria
VermelhaFactory --> RetanguloVermelho : cria
AzulFactory --> CirculoAzul : cria
AzulFactory --> RetanguloAzul : cria
Código Fonte (Solução — Abstract Factory)
Exemplo 2 — CMS: Família de Componentes de UI (Tema Light/Dark)
- Queremos gerar páginas estáticas com tema.
- Cada tema fornece uma família consistente de componentes (
Navbar, Button).
- Trocar o tema = trocar a fábrica.
classDiagram
direction LR
class UiFactory {
<<interface>>
+createNavbar(title): Navbar
+createButton(label): Button
}
class LightUiFactory
class DarkUiFactory
class Navbar { <<interface>> +html():String }
class Button { <<interface>> +html():String }
class LightNavbar
class LightButton
class DarkNavbar
class DarkButton
UiFactory <|.. LightUiFactory
UiFactory <|.. DarkUiFactory
Navbar <|.. LightNavbar
Button <|.. LightButton
Navbar <|.. DarkNavbar
Button <|.. DarkButton
Código Fonte (Solução CMS — Abstract Factory)
Observações finais (para aula)
- Quando usar: quando há famílias de produtos que devem variar juntas (tema, fornecedor, região, protocolo).
- Vantagens: consistência entre produtos, troca de família por injeção, isolamento de classes concretas.
- Trade-offs: mais classes; difícil “misturar” produtos de famílias diferentes (by design).
- Comparações:
- vs Factory Method: AF cria múltiplos produtos correlatos; FM foca em um produto por hierarquia.
- vs Builder: AF escolhe famílias; Builder monta passo a passo um objeto complexo.