GoF, p. 107 também chamado de Virtual Constructor
Método Fábrica
Factory Method
A superclasse define o esqueleto; a subclasse decide qual objeto criar.
Definir uma interface para criar um objeto, mas deixar as subclasses decidirem qual classe instanciar. Factory Method permite que uma classe adie a instanciação para subclasses.
A transportadora
Sua empresa começou só com caminhões: toda a logística estava escrita em cima da classe Caminhão. Aí chegou o transporte marítimo. Reescrever tudo com `if (é navio)` seria um pesadelo. Em vez disso, a logística passa a pedir “me dê um transporte” a um método que as subclasses sobrescrevem: LogísticaTerrestre devolve Caminhão, LogísticaMarítima devolve Navio. O roteiro de entrega continua idêntico.
Uma classe precisa criar objetos, mas não deve (ou não pode) saber de antemão qual classe concreta será. Chamar `new ClasseConcreta()` direto no meio da lógica prende o código a ela para sempre.
Substitua as chamadas diretas a `new` por chamadas a um método fábrica sobrescrevível. A superclasse programa contra a interface do produto; cada subclasse retorna a variante que lhe cabe.
switch (tipo) { case "pdf": return new PDF(); ... }repetido em vários lugares.newde classe concreta dentro de uma classe de alto nível.
Estrutura
- Product
- Interface comum a tudo que o método fábrica pode retornar.
- ConcreteProduct
- Implementações específicas do produto.
- Creator
- Declara o método fábrica e contém a lógica de negócio que usa o produto.
- ConcreteCreator
- Sobrescreve o método fábrica para devolver um produto concreto.
Implementação
// ── Produto ───────────────────────────────────────────
class Documento {
serializar(dados) { throw new Error('abstrato'); }
get extensao() { throw new Error('abstrato'); }
}
class DocCSV extends Documento {
serializar(d) { return d.map(l => Object.values(l).join(',')).join('\n'); }
get extensao() { return 'csv'; }
}
class DocJSON extends Documento {
serializar(d) { return JSON.stringify(d, null, 2); }
get extensao() { return 'json'; }
}
// ── Creator: a lógica de negócio vive AQUI, uma vez só ─
class Exportador {
// ↓ o Factory Method. As subclasses respondem a esta pergunta.
criarDocumento() { throw new Error('subclasse deve implementar'); }
// Este método NUNCA muda quando surge um novo formato.
exportar(dados) {
const doc = this.criarDocumento();
const conteudo = doc.serializar(dados);
return { nome: `relatorio.${doc.extensao}`, bytes: conteudo.length, conteudo };
}
}
class ExportadorCSV extends Exportador { criarDocumento() { return new DocCSV(); } }
class ExportadorJSON extends Exportador { criarDocumento() { return new DocJSON(); } }
const dados = [{ id: 1, nome: 'Ana' }, { id: 2, nome: 'Bruno' }];
console.log(new ExportadorCSV().exportar(dados).nome); // relatorio.csv
console.log(new ExportadorJSON().exportar(dados).nome); // relatorio.json - java.util.Calendar.getInstance()
- java.net.URLStreamHandlerFactory
- React.createElement — a raiz de todo componente
Consequências
- Elimina o acoplamento entre o criador e os produtos concretos.
- Centraliza a criação num único ponto, fácil de estender.
- Novos produtos entram sem tocar no código existente (Aberto/Fechado).
- Pode gerar muitas subclasses só para variar a criação.
- Introduz uma hierarquia paralela (creators espelhando products).
- Você não sabe de antemão os tipos exatos com que seu código vai trabalhar.
- Você quer dar aos usuários da sua biblioteca um jeito de estender seus componentes internos.
- Você quer reaproveitar objetos caros em vez de recriá-los (o método fábrica pode devolver de um pool).
- Só existe um tipo de produto e não há sinal de um segundo.
- Uma função simples que recebe o tipo por parâmetro já resolve (a “simple factory”, que não é GoF).
Relações com outros padrões
- Abstract Factory
- Abstract Factory é frequentemente um conjunto de Factory Methods.
- Template Method
- Factory Method costuma ser uma etapa dentro de um Template Method.
- Iterator
- Uma coleção usa um Factory Method para devolver o iterador adequado.
- Prototype
- Prototype não exige subclasses, mas exige inicialização do protótipo.
Verificação
Qual afirmação distingue corretamente Factory Method de Abstract Factory?
- Factory Method cria UM produto via herança; Abstract Factory cria uma FAMÍLIA via composição
- Factory Method é mais lento porque usa reflexão
- Abstract Factory só funciona com objetos imutáveis
- Factory Method exige uma classe Director
Factory Method é um padrão de escopo de CLASSE (usa herança: a subclasse decide). Abstract Factory é de escopo de OBJETO (o cliente recebe uma fábrica por composição).