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 código, perdemos a semântica do significado dos parâmetros 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 parâmetros.
Criar um , ou mais, métodos estáticos que têm nomes claros, especificam o que os parâmetros 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 construtor 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 impossível determinar qual a forma que o programador está usado. Além de que não é possível criar dois construtores com o mesmo numero e tipo de parâmetros.
// atenção: este código não compila public class Complex{ public Complex(double real, double imaginary){ //constroi de um jeito ... } public Complex(double angle, double phase){ // constrói de outro ... } }
O uso de Static Factory Method possibilita ainda poder fazer cache dos valores ou retornar
valores constantes. 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 parâmetros.
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 incluída a funcionalidade de Enumerações. Todas as enumeraçõ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 deixa possível que os métodos criadores que contém otimizações de performance e cache não sejam usados. 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 instâncias de Value Object ou Singleton.
Referências
[1] |
Effetive Java
Livro:Effetive Java |
[2] |
Java Tip #2: Static factory methods vs. constructors
URL: |