Submarino.com.br

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
	
}			
			
Código 1:

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
		...
	 }
}
			
Código 2: Código impossível

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;
			}
			
Código 3:

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: Java Tip #2: Static factory methods vs. constructors http://blog.codefront.net/2003/06/21/java-tip-2-static-factory-methods-vs-constructors/