Reflexões sobre desenvolvimento de software (only in Portuguese)

segunda-feira, 2 de novembro de 2015

Static Factory methods em vez de construtores

A forma que a linguagem Java oferece para criar objetos é através de um construtor. Entretanto construtores possuem algumas características que podem se tornar limitações em alguns contextos.

Java considerará como construtores métodos que possuem o mesmo nome de sua classe. Isso é bom pois cria uma padronização, mas ruim quando por exemplo, você precisa de dois ou mais construtores que inicializam suas novas instâncias de maneira diferente. Nesse caso você tem três possibilidades.

1. Uma abordagem é sobrecarregar o construtor com outra assinatura. Com diferentes tipos de parâmetros, ou pior ainda, apenas mudando a ordem deles. Essa abordagem é muito ruim pois a pessoa que for ler o código que usa esses diferentes construtores não conseguirá diferencia-los e pode facilmente confundi-los. Obriga a pessoa a ver a implementação dos seus construtores. Código torna-se pouco legível. Não use.

2. Uma boa abordagem é questionar: porque preciso desse outro construtor? Minha classe não está ficando complexa? Reflita e se a resposta que você precisa, use static factory methods.

A técnica é bastante simples: é um método estático que retornará a nova instância de sua classe chamando o construtor em sua implementação. Como para o compilador esse método é um método como qualquer outro, você pode dar um nome que exprima de maneira adequada o seu uso e sua intenção.
A api de Java tem um ótimo exemplo desse uso. Esse construtor da classe BigInteger(int int, Random)retorna um BigInteger com alta probabilidade de ser um número primo. Confuso né? Por isso que na release 1.4 de Java foi incluído o static factory method BigInteger.probablePrime.Apenas dar um nome com significado em vez de usar um construtor tornou o código extremamente mais fácil de ler. E isso se converte em horas economizadas uma vez que você e toda sua equipe vai ler esse código várias vezes durante o desenvolvimento.

É por isso que static factory methods embora simples, são uma ferramenta que deve estar no cinto de utilidades de todo programador Java.

Existem outras vantagens interessantes de static factory methdos:

1. São eles que permitem os design patterns Singleton e FlyWeight.

2. Ao contrário de construtores, podem retornar subtipos  do tipo de retorno, dando grande flexibilidade.

Como desvantagens, podemos citar:

1. Caso você opte por remover o construtor tornando ele privado e usar apenar um static factory method, sua classe não será subclasseavel. Desvantagem bem específica e pouco impactante.

2. Agora uma desvantagem de fato: static factory methods não se destacam na sua api do mesmo modo que um construtor. Quando você vê um construtor, você sabe que ele forçosamente vai retornar uma nova instância da sua classe. Dependendo do nome que você der para seu static factory method, pode ficar um pouquinho difícil de ver que ali temos um método que tem o papel de um construtor. É por isso que é interessante usar algum desses padrões já bastante usados na própria api da linguagem:
  • valueOf --> Retorna instância descrito por seus parâmetros. São de fato conversores. Exemplo clássico: Integer.valueOf(3). Esse método retorná o objeto 3 a partir do primitivo 3.
  • of --> Versão concisa do valueOf popularizada pelo EnumSet.
  • getInstance -->  bastante usado em singletons.
  • newInstance --> garante que uma nova instância será retornada, contrastando com getInstance.
Resumindo: evite o reflexo imediato de prover um construtor público e reflita se um static factory method não tornará sua api mais legivel e fácil de usar

Fonte: Effective Java do Joshua Bloch. Leiam !!!