Static Factory Method
Objetivo
Documentar e/ou simplificar a criação de um objeto substituindo o uso do construtor por um método estático explicito.
Propósito
Quando usamos um construtor diretamente no codigo, perdemos a semantica do significado dos parametros e perdemos controle sobre a inicialização do objeto. Isso tem implicações na nomenclatura e na documentação do código porque sempre que o programador se depara com um construtor tem que consultar o javadoc para saber o significado de cada parametros.
Criar um , ou mais, métodos estáticos que têm nomes claros, especificam o que os parametros significam e encapsulam a real criação do objeto é uma forma simples de ganhar muita produtividade, diminuir acoplamento e aumentar a legibilidade[1].
Implementação
A implementação deste padrão é muito simples. Basta declarar o constutor privado e criar um método ou mais métodos estáticos que realmente criam o objeto.
public class Complex {
public static Complex real(double real){
return complex(real,0.0);
}
public static Complex imaginary(double imaginary){
return complex(0.0,imaginary);
}
public static Complex complex(double real, double imaginary){
return new Complex(real,imaginary);
}
public static Complex polar(double amplitude, double phase){
double real = amplitude * Math.cos(phase);
double imaginary = amplitude * Math.sin(phase);
return new Complex(real,imaginary);
}
private static Complex ONE = return new Complex(1,0);
private static Complex ZERO = return new Complex(0,0);
private static Complex I = return new Complex(0,0);
public static Complex one(){
return ONE;
}
public static Complex zero(){
return ZERO;
}
public static Complex i(){
return I;
}
private Complex(double real, double imaginary){
this.real = real;
this.imaginary = imaginary;
}
// resto dos métodos da classe
}
Para cria um número complexo são precisos dois valores. Um para parte real e outro para a parte imaginária. Contudo esses valores podem ser dados em forma geométrica ou em forma polar. Apenas usando construtores seria impossivel determinar qual a forma que o programador está usado. Além de que não é possivel criar dois construtores com o mesmo numero e tipo de parametros.
// atenção: este codigo não compila
public class Complex{
public Complex(double real, double imaginary){
//constroi de um jeito
...
}
public Complex(double angle, double phase){
// constroi de outro
...
}
}
O uso de Static Factory Method possibilita ainda poder fazer cache dos valores ou retornar
valores constances. Podemos ver esta técnica sendo usada com ONE, ZERO e I.
Note ainda que os métodos de construção podem ter ou não ter parametros.
Discussão
O padrão Static Factory Method é, em geral, uma alternativa melhor ao uso de construtores. Permite criar os objetos sem expor a forma de criação ou carecer do uso do operador new.
Além disso permite que modifiquemos a forma de criação ou incluamos mecanismos de cache.
Exemplos na API padrão
Existem muitos exemplos na API padrão do uso de Static Factory Method principalmente
nos objetos wrapper como Integer e BigDecimal
nos métodos valueOf. No caso de Integer existe até um mecanismo de cache de valores
que auxiliar a aumentar a performance das operações de auto-boxing.
As classes Calendar e Locale
também fazem uso de Static Factory Method nos métodos getInstance.
A partir do Java 5 foi incluida a funcionalidade de Enumerações. Todas as enumarações contam com métodos
valueOf() que são implementações de Static Factory Method.
Finalmente, um caso mais interessante do uso de Static Factory Method é o método valueOf
da classe Boolean. Este método apenas retorna Boolean.TRUE ou
Boolean.TRUE e a única coisa que ele faz é decidir qual, algo assim:
public Boolean valueOf(boolean value){
return value ? Boolean.TRUE : Boolean.FALSE;
}
Este método parece que vai criar um objeto, mas na realidade não o faz. Utilizar este método em vez de new Boolean(value)
preserva a JVM de ficar criando e destruindo um monte de objetos iguais melhorando a performance da aplicação e demonstra perfeitamente
que o uso de Static Factory Method não está apenas vinculado ao ato de criar, mas principalmente ao ato de simular
a criação.
O uso de Static Factory Method nas classes wrapper na biblioteca padrão foram adicionados vários anos depois da criação original das classes. Isto significa que nunca poderemos tornar os construtores privados e força o uso dos métodos criadores que contém otimizações de performance e cache. Este é um exemplo de porquê devemos sempre presar pelo encapsulamento de decisões, especialmente a decisão de instanciação.
Padrões associados
Como o próprio nome indica Static Factory Method é uma derivação do padrão Factory Method onde o fator da herança e polimorfismo das fábricas é removido.
Static Factory Method pode ser associada a qualquer tipo de objeto, mas é normalmente mais usual vê-lo associado a objetos que também são instancias de Value Object.
Referências
| [1] |
Effetive Java
Livro:Effetive Java |
| [2] |
Java Tip #2: Static factory methods vs. constructors
URL: |