Padrões Criacionais
Intenção da categoria
Seção intitulada “Intenção da categoria”Quando o código faz new ClasseConcreta() diretamente, ele fica amarrado a essa classe. Os padrões criacionais movem essa decisão para trás de uma abstração, permitindo variar o tipo e o processo de criação sem mexer no cliente. Isso realiza OCP (novas variações entram como novas classes) e DIP (o cliente depende de abstrações).
Os cinco padrões
Seção intitulada “Os cinco padrões”Factory Method
Seção intitulada “Factory Method”Intenção: define uma interface para criar um objeto, mas deixa subclasses decidirem qual classe concreta instanciar.
Quando usar: quando uma classe não sabe de antemão a classe concreta que deve criar, ou quer delegar essa escolha a subclasses. Comum em frameworks que definem o esqueleto e deixam o cliente preencher o “que” é criado.
Abstract Factory — ver Abstract Factory
Seção intitulada “Abstract Factory — ver Abstract Factory”Intenção: fornece uma interface para criar famílias de objetos relacionados sem especificar suas classes concretas.
Quando usar: quando o sistema deve ser independente de como seus produtos são criados e precisa garantir que produtos de uma mesma família sejam usados juntos (ex: um kit de widgets por tema de UI). Contraste detalhado com Factory Method na nota Abstract Factory.
Builder — ver Builder
Seção intitulada “Builder — ver Builder”Intenção: separa a construção de um objeto complexo de sua representação, permitindo montá-lo passo a passo.
Quando usar: quando a criação envolve muitos parâmetros (especialmente opcionais), montagem em várias etapas ou variações de representação. Evita o telescoping constructor. Detalhes e alternativa a record na nota Builder.
Prototype
Seção intitulada “Prototype”Intenção: cria novos objetos clonando uma instância protótipo, em vez de instanciar a classe do zero.
Quando usar: quando o custo de criar do zero é alto, quando as classes a instanciar são definidas em tempo de execução, ou quando se quer evitar uma hierarquia de fábricas paralela à de produtos. Em Java, envolve clone() (raso vs. profundo) ou construtores de cópia.
Singleton
Seção intitulada “Singleton”Intenção: garante que uma classe tenha uma única instância e fornece um ponto global de acesso a ela.
Quando usar: quando é logicamente necessário exatamente um objeto (um registro de configuração imutável, um pool). Fora esses casos, geralmente há alternativa melhor.
Alerta sobre Singleton
Seção intitulada “Alerta sobre Singleton”O Singleton é o padrão criacional mais abusado. Seus custos costumam superar os benefícios:
- Acoplamento global disfarçado:
Config.getInstance()espalhado pelo código cria dependências ocultas — nenhuma assinatura de método revela que a classe depende do singleton. Isso viola o espírito do DIP: em vez de receber a dependência, o objeto vai buscá-la globalmente. - Atrapalha testes: estado global compartilhado entre testes causa acoplamento temporal e ordem-dependência; substituir por um dublê exige truques (reflection, subclasses). Ver Testabilidade e Arquitetura.
- Esconde a verdadeira cardinalidade: quase sempre o que se quer é “uma instância gerenciada pelo container”, não “uma instância imposta pela própria classe”.
Alternativa recomendada: injetar a dependência (um único bean com escopo singleton no container de DI). O ciclo de vida vira responsabilidade da composição da aplicação, não da classe, preservando testabilidade e explicitando a dependência.
public enum ConfiguracaoApp { INSTANCIA; private final String url = "jdbc:postgresql://localhost/app"; public String url() { return url; }}O enum acima é a forma segura de Singleton em Java (serialização e concorrência resolvidas pela JVM) — mas prefira DI mesmo assim, exceto para constantes verdadeiramente imutáveis.
Diagrama de posicionamento
Seção intitulada “Diagrama de posicionamento”classDiagram
class Cliente
class Criador {
<<abstract>>
+criar() Produto
}
class Produto {
<<interface>>
}
class ProdutoConcretoA
class ProdutoConcretoB
Cliente --> Criador : usa
Cliente --> Produto : consome abstração
Criador ..> Produto : cria
Produto <|.. ProdutoConcretoA
Produto <|.. ProdutoConcretoB
Anti-padrões e erros comuns
Seção intitulada “Anti-padrões e erros comuns”- Singleton como variável global: usar Singleton para carregar estado mutável acessível de qualquer lugar. É acoplamento global com outro nome.
- Fábrica que não abstrai nada: uma “factory” que só encapsula um único
newsem ponto de variação é indireção inútil. - Builder para objetos triviais: um Builder para uma classe de dois campos obrigatórios é over-engineering — um construtor ou
recordbasta. - Prototype com
clone()raso onde precisava ser profundo: compartilhar referências mutáveis entre clones gera bugs sutis.
Relações
Seção intitulada “Relações”- Notas próprias da categoria: Builder, Abstract Factory.
- Categoria irmã: Padrões Estruturais, Padrões Comportamentais.
- Índice: Design Patterns (GoF).
- Princípios: OCP - Open-Closed Principle, DIP - Dependency Inversion Principle.
- Impacto em testes: Testabilidade e Arquitetura.
Perguntas de revisão
Seção intitulada “Perguntas de revisão”1. Qual problema comum todos os padrões criacionais atacam?
Resposta
A dependência direta do cliente em classes concretas via new. Eles encapsulam qual classe instanciar e como montá-la atrás de uma abstração, favorecendo OCP e DIP.
2. Por que o Singleton é problemático para testes?
Resposta
Ele impõe estado global compartilhado e acesso via método estático, criando dependências ocultas e acoplamento entre testes (ordem-dependência). Substituí-lo por um dublê é difícil. A alternativa é injeção de dependência com escopo singleton gerenciado pelo container.
3. Quando escolher Builder em vez de um construtor simples?
Resposta
Quando há muitos parâmetros (especialmente opcionais), montagem em etapas ou diferentes representações do mesmo processo de construção. Para objetos simples, prefira construtor ou record — Builder aí seria over-engineering.
4. Qual a diferença essencial entre Factory Method e Abstract Factory?
Resposta
Factory Method cria um produto e delega a escolha da classe concreta a subclasses (via herança/sobrescrita de um método). Abstract Factory cria famílias de produtos relacionados através de composição de um objeto-fábrica. Ver Abstract Factory.