Pular para o conteúdo

Abstract Factory

O Abstract Factory é um padrão de projeto criacional que oferece uma interface para criar famílias de objetos relacionados (ou dependentes) sem especificar suas classes concretas.

Em vez de o código do cliente instanciar diretamente new BotaoWindows() ou new BotaoMac(), ele recebe uma fábrica (ex.: WindowsFactory ou MacFactory) capaz de produzir um conjunto coerente de componentes.

Ideia central: “Se eu escolhi a família Windows, tudo que eu criar deve ser Windows (botão, checkbox, etc.).”


Imagine uma aplicação que suporta múltiplos temas/ambientes, por exemplo:

  • Interface Windows
  • Interface macOS

Você já tem componentes como:

  • Botão
  • Checkbox

Se o cliente criar objetos diretamente, surgem problemas comuns:

  1. Acoplamento: o código fica cheio de new ...Windows / new ...Mac.
  2. Mistura indevida de famílias: dá para acabar com BotaoWindows + CheckboxMac no mesmo contexto.
  3. Baixa extensibilidade: adicionar uma nova família (ex.: Linux) exige revisar muitos pontos do código.

O Abstract Factory propõe:

  1. Definir interfaces de produto (ex.: Button, Checkbox).
  2. Definir uma interface de fábrica com métodos para criar cada produto (ex.: createButton(), createCheckbox()).
  3. Criar fábricas concretas para cada família (ex.: WindowsFactory, MacFactory) que produzem produtos compatíveis entre si.
  4. O cliente recebe uma fábrica e cria tudo por ela, sem conhecer as classes concretas.

  • AbstractFactory: declara métodos de criação (um por tipo de produto).
  • ConcreteFactory: implementa os métodos para uma família específica.
  • AbstractProduct: interface de cada produto (ex.: Button).
  • ConcreteProduct: implementação do produto para a família (ex.: WindowsButton).
  • Client: usa apenas interfaces (factory + products), sem new de concretos.

  • Button e Checkbox são interfaces (contrato).
  • O cliente só conhece esses contratos.
  • WindowsButton e WindowsCheckbox
  • MacButton e MacCheckbox
  • GUIFactory (abstract)
  • WindowsFactory / MacFactory (concrete)
// Produtos abstratos
interface Button {
void render();
}
interface Checkbox {
void toggle();
}
// Produtos Windows
class WindowsButton implements Button {
@Override
public void render() {
System.out.println("Renderizando botão no estilo Windows");
}
}
class WindowsCheckbox implements Checkbox {
@Override
public void toggle() {
System.out.println("Alternando checkbox no estilo Windows");
}
}
// Produtos macOS
class MacButton implements Button {
@Override
public void render() {
System.out.println("Renderizando botão no estilo macOS");
}
}
class MacCheckbox implements Checkbox {
@Override
public void toggle() {
System.out.println("Alternando checkbox no estilo macOS");
}
}
// Fábrica abstrata
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
// Fábricas concretas (famílias)
class WindowsFactory implements GUIFactory {
@Override
public Button createButton() { return new WindowsButton(); }
@Override
public Checkbox createCheckbox() { return new WindowsCheckbox(); }
}
class MacFactory implements GUIFactory {
@Override
public Button createButton() { return new MacButton(); }
@Override
public Checkbox createCheckbox() { return new MacCheckbox(); }
}
// Cliente
class Application {
private final Button button;
private final Checkbox checkbox;
Application(GUIFactory factory) {
this.button = factory.createButton();
this.checkbox = factory.createCheckbox();
}
void run() {
button.render();
checkbox.toggle();
}
}
// Bootstrap
public class Main {
public static void main(String[] args) {
GUIFactory factory = chooseFactoryByOS("windows"); // simulado
new Application(factory).run();
}
static GUIFactory chooseFactoryByOS(String os) {
if ("mac".equalsIgnoreCase(os)) return new MacFactory();
return new WindowsFactory();
}
}

O que observar:

  • O Application não sabe o que é WindowsButton nem MacButton.
  • Ao trocar WindowsFactory por MacFactory, a aplicação muda de família inteira (coerente).

Use Abstract Factory quando:

  • Você precisa criar famílias de objetos que devem ser compatíveis entre si.
  • Você quer isolar a criação de objetos do restante do código.
  • Você precisa trocar “tema/ambiente/driver/fornecedor” sem reescrever o cliente.

Exemplos típicos:

  • GUI multi-plataforma (Windows/macOS/Linux)
  • Conectores para bancos (MySQL/Postgres) com famílias de objetos (conexão, comando, transação)
  • Integrações com provedores (AWS/Azure/GCP) com serviços correspondentes

  • Garante consistência entre produtos da mesma família.
  • Reduz acoplamento do cliente com classes concretas.
  • Facilita trocar famílias (ex.: Windows → macOS) com poucas mudanças.
  • Aumenta o número de classes/interfaces.
  • Se você adicionar um novo tipo de produto (ex.: Slider), precisa alterar a fábrica abstrata e todas as fábricas concretas.

  • Factory Method: cria um tipo de produto via herança/polimorfismo; bom quando há um foco em um produto principal.
  • Abstract Factory: cria famílias de produtos (botão + checkbox + etc.), garantindo compatibilidade.
  • Builder: foca em construir um objeto complexo passo a passo; não é sobre famílias compatíveis.

Pergunte:

  • “Tenho variações (Windows/Mac) e múltiplos produtos (botão/checkbox) que precisam combinar?”
  • “Quero escolher uma família em tempo de execução/configuração e o restante deve seguir essa escolha?”

Se sim, Abstract Factory é um forte candidato.