Item 1: Considere os métodos Static Factory em vez de construtores
O modo tradicional para uma classe permitir que uma cliente obtenha uma instância é fornecer um construtor público. Há outra técnica que deve fazer parte do conjunto do java toolkit de todo programador. Uma classe pode fornecer um método static factory public, que é simplemente um método estático que retorna uma instância de classe.
Por que usar Static Factory Methods no Java?
Quem trabalha com Java no dia a dia está mais do que acostumado a instanciar objetos usando a palavra reservada new. É o padrão que aprendemos no início da carreira e que muitas vezes reproduzimos no piloto automático. Porém, quando começamos a olhar para a nossa base de código com a mentalidade de um Arquiteto de Software, percebemos que o caminho mais comum nem sempre é o ideal para aplicações robustas.
O Problema dos Construtores Tradicionais
A principal limitação de um construtor é que ele não conta uma história. Ele obrigatoriamente tem o mesmo nome da classe e, se você precisar de variações, terá que criar múltiplas assinaturas que se diferenciam apenas pela ordem ou tipo dos parâmetros.
Imagine instanciar um cartão de estudos dinâmico:
Java
// O que significa esse "true" e esse "1"?
Flashcard card = new Flashcard("O que é Polimorfismo?", "Múltiplas formas", true, 1);
Fica difícil para outro desenvolvedor bater o olho e entender a intenção de negócio por trás dessa chamada.
A Solução: Static Factory Methods
A proposta de Joshua Bloch é simples e elegante: oculte seus construtores (deixando-os private) e crie métodos estáticos públicos que retornam uma instância da classe.
Olha como a legibilidade muda completamente:
Java
public class Flashcard {
private String pergunta;
private String resposta;
// Construtor privado: bloqueamos o uso do "new" externamente
private Flashcard(String pergunta, String resposta) {
this.pergunta = pergunta;
this.resposta = resposta;
}
// Static Factory Method 1
public static Flashcard criarParaRevisaoAtiva(String pergunta, String resposta) {
Flashcard card = new Flashcard(pergunta, resposta);
// Aplica lógicas específicas de negócio, como peso de revisão...
return card;
}
// Static Factory Method 2
public static Flashcard criarRascunho(String pergunta) {
return new Flashcard(pergunta, "Resposta pendente");
}
}
Uso prático:
Java
Flashcard revisao = Flashcard.criarParaRevisaoAtiva("O que é DDD?", "Domain-Driven Design");
A leitura do código se torna fluida, quase como um texto em inglês. Mas a legibilidade não é o único benefício.
As 3 Grandes Vantagens na Arquitetura
Além de dar nomes descritivos à criação dos seus objetos, adotar esse padrão traz benefícios profundos de performance e design:
1. Controle de Instâncias (Economia de Memória): Diferente do operador new, que sempre aloca um novo espaço na memória RAM, um método estático pode retornar um objeto que já está em cache. O próprio Java faz isso: chamar Boolean.valueOf(true) não cria um objeto novo, apenas devolve a constante que já existe.
2. Retorno de Subtipos (Ocultação de Complexidade): Um método de fábrica pode retornar qualquer classe que estenda a classe original ou implemente uma interface. Isso permite que você mude a classe concreta por baixo dos panos sem quebrar o código de quem está chamando sua API. (É exatamente assim que o List.of() funciona nas versões mais recentes do Java).
3. Flexibilidade Dinâmica: A classe do objeto retornado pode variar dependendo dos parâmetros passados. Se uma lista for pequena, a fábrica pode retornar uma implementação otimizada para poucos itens; se for grande, retorna outra versão, tudo de forma transparente para o usuário final.
Nem tudo é perfeito
Classes que possuem apenas construtores privados não podem ser herdadas (extends). No entanto, na arquitetura moderna, isso frequentemente é visto como um benefício, já que nos força a usar Composição em vez de Herança, um princípio fundamental do Clean Code.
Conclusão
Abandonar o uso desenfreado do new e adotar métodos de fábrica estáticos é um daqueles pequenos ajustes de mentalidade que elevam instantaneamente o nível do seu código. É um passo essencial para quem deseja construir APIs mais limpas, seguras e eficientes.
Você já conhecia ou aplicava esse padrão nos seus projetos? Deixe nos comentários como tem sido a sua experiência!