Pular para o conteúdo
GoF Padrões de Projeto Criacionais
Criacional escopo de objeto
GoF, p. 87 também chamado de Kit

Fábrica Abstrata

Abstract Factory

Uma fábrica de fábricas: cria famílias inteiras de objetos combináveis.

Complexidade alta Frequência de uso muito comum
Intençãocomo o livro define

Fornecer uma interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.

Analogiauma imagem do mundo real

A loja de móveis por estilo

Você entra numa loja e escolhe o estilo: Vitoriano ou Moderno. A partir daí, o sofá, a poltrona e a mesinha de centro que você recebe combinam entre si — você nunca pediu “o sofá vitoriano”, pediu “um sofá” para a loja vitoriana. Trocar de estilo é trocar de loja, e todo o conjunto muda junto, sem risco de misturar um sofá moderno com uma poltrona vitoriana.

O problema

Seu sistema precisa produzir vários objetos que só fazem sentido juntos (uma “família”). Se cada ponto do código instanciar a classe concreta diretamente com `new`, duas coisas ruins acontecem: (1) espalha-se a decisão de “qual família usar” por dezenas de arquivos, e (2) nada impede que alguém misture peças de famílias diferentes e quebre a coerência.

A solução

Declare uma interface para cada produto da família (Cadeira, Sofá, Mesa) e uma interface de fábrica com um método de criação por produto. Cada família concreta ganha sua própria fábrica, que só sabe produzir peças compatíveis entre si. O cliente recebe a fábrica pronta e conversa apenas com as interfaces — ele nunca vê uma classe concreta.

Sintomascomo reconhecer no seu código
  • Vários if (tema === "escuro") espalhados decidindo qual classe instanciar.
  • Bugs do tipo “botão do tema claro apareceu na tela escura”.

Estrutura

usausacriacriaClient«interface»AbstractFactory+ criarCadeira()+ criarSofa()FabricaVitorianaFabricaModerna«interface»Cadeira+ sentar()CadeiraVitorianaCadeiraModerna
Fig. 1 — Abstract Factory herda / implementa cria usa / contém
Ver este diagrama sendo desenhado, traço a traço
Participantes
AbstractFactory
Declara os métodos de criação, um por tipo de produto.
ConcreteFactory
Implementa a criação de uma família específica e coerente.
AbstractProduct
Interface comum a todas as variantes de um mesmo produto.
ConcreteProduct
Produto de uma família, criado pela fábrica correspondente.
Client
Usa apenas AbstractFactory e AbstractProduct.

Implementação

Listagem 1 Uma família de componentes de UI por sistema operacional
// ── Produtos abstratos ────────────────────────────────
class Botao   { render() { throw new Error('abstrato'); } }
class Checkbox{ render() { throw new Error('abstrato'); } }

// ── Família 1: macOS ──────────────────────────────────
class BotaoMac    extends Botao    { render() { return '🍎 [ botão arredondado ]'; } }
class CheckboxMac extends Checkbox { render() { return '🍎 ( ✓ )'; } }

// ── Família 2: Windows ────────────────────────────────
class BotaoWin    extends Botao    { render() { return '🪟 [ botão retangular ]'; } }
class CheckboxWin extends Checkbox { render() { return '🪟 [x]'; } }

// ── A fábrica abstrata: um método por produto ─────────
class FabricaUI {
  criarBotao()    { throw new Error('abstrato'); }
  criarCheckbox() { throw new Error('abstrato'); }
}

// Cada fábrica concreta produz SÓ peças coerentes entre si.
class FabricaMac extends FabricaUI {
  criarBotao()    { return new BotaoMac(); }
  criarCheckbox() { return new CheckboxMac(); }
}
class FabricaWin extends FabricaUI {
  criarBotao()    { return new BotaoWin(); }
  criarCheckbox() { return new CheckboxWin(); }
}

// ── Cliente: não conhece NENHUMA classe concreta ──────
function renderizarFormulario(fabrica) {
  const botao = fabrica.criarBotao();
  const check = fabrica.criarCheckbox();
  return [check.render(), botao.render()].join('\n');
}

// A escolha da família acontece em UM único lugar.
const fabrica = navigator.platform.startsWith('Mac')
  ? new FabricaMac()
  : new FabricaWin();

console.log(renderizarFormulario(fabrica));
Na práticaonde ele já existe
  • javax.xml.parsers.DocumentBuilderFactory (Java)
  • java.awt.Toolkit — cria peças de UI da plataforma
  • Drivers de banco: cada driver produz Connection, Statement e ResultSet coerentes

Consequências

A favor
  • Garante que os produtos usados juntos sejam sempre compatíveis.
  • Elimina o acoplamento entre o código cliente e as classes concretas.
  • Concentra a criação em um só lugar (Princípio da Responsabilidade Única).
  • Adicionar uma nova família não exige tocar no cliente (Aberto/Fechado).
Contra
  • Muitas interfaces e classes novas — só compensa se houver famílias de verdade.
  • Adicionar um novo TIPO de produto obriga a alterar a interface da fábrica e TODAS as fábricas concretas.
Use quando
  • Seu sistema precisa funcionar com várias famílias de produtos e você quer poder trocar a família inteira.
  • Você quer impedir, por construção, que peças incompatíveis sejam combinadas.
  • Você tem uma classe com um monte de Factory Methods que já estão obscurecendo sua responsabilidade principal.
Evite quando
  • Existe só uma família e nenhuma perspectiva realista de uma segunda.
  • Os produtos não têm relação entre si — aí você quer Factory Methods separados, não uma família.

Relações com outros padrões

evolui para
Factory Method
Uma Abstract Factory costuma ser um conjunto de Factory Methods. É a evolução natural quando aparece a segunda família.
alternativa a
Prototype
A fábrica concreta pode clonar protótipos em vez de dar `new`.
costuma andar junto
Singleton
Fábricas concretas normalmente precisam de uma única instância.
Bridge
Abstract Factory encapsula as relações da Bridge e esconde a complexidade do cliente.
parecido / fácil de confundir
Builder
Abstract Factory devolve o produto pronto de imediato; Builder monta passo a passo.

Verificação

Questãoa resposta está marcada

Qual é o principal problema que Abstract Factory resolve e que Factory Method sozinho não resolve?

  1. Garantir que objetos criados em conjunto sejam de uma mesma família compatível
  2. Garantir que exista apenas uma instância de cada objeto
  3. Permitir clonar objetos existentes em vez de criá-los do zero
  4. Montar um objeto complexo em várias etapas configuráveis

Factory Method cria UM produto. Abstract Factory cria uma FAMÍLIA e, por construção, impede que você misture um botão macOS com um checkbox Windows.