Se uma classe depender internamente de um ou mais recursos e esses recursos influenciarem o comportamento da classe, é recomendável não utilizar classes singleton e utilitárias estáticas.
Em vez de a classe criar esses recursos diretamente, é preferível passá-los para o construtor. A injeção de dependência pode melhorar a flexibilidade, a reusabilidade e a facilidade de teste da classe.
Exemplo
Exemplo de uso de classe utilitária estática
Essa classe utilitária presume que apenas um dicionário será usado. No entanto, na prática, pode haver dicionários separados para cada idioma e, até mesmo, dicionários específicos para vocabulário especializado.
Exemplo de uso de classe singleton
Da mesma forma, a classe singleton também presume que apenas um dicionário será usado, levando aos mesmos problemas mencionados anteriormente.
Solução 1 - Remover a palavra-chave final do campo
É possível remover a palavra-chave final do atributo dictionary em uma classe utilitária estática ou singleton e permitir que o dicionário seja substituído por outro de fora. No entanto, essa abordagem é complicada e pode causar problemas de concorrência em ambientes multithread.
Solução 2 - Usar injeção de dependência
Através dos exemplos acima, podemos perceber que classes estáticas e singleton não devem depender de recursos internos. Ou seja, é preferível que os recursos internos sejam injetados de fora.
Uma classe que utiliza injeção de dependência garante imutabilidade graças à palavra-chave final e suporta múltiplas instâncias de recursos. Além disso, a injeção de dependência pode ser aplicada não apenas no construtor, mas também em métodos estáticos de fábrica e builders.
A injeção de dependência pode simplesmente passar o próprio recurso, mas também é comum passar uma fábrica de recursos. Uma fábrica é um objeto que cria repetidamente instâncias de um determinado tipo quando chamado. Esse padrão é conhecido como Padrão de Fábrica (Factory Method Pattern), e o Supplier<T> do Java 8 é um ótimo exemplo de como representar uma fábrica.
Geralmente, um tipo curinga limitado é usado para restringir o parâmetro de tipo da fábrica. Com essa abordagem, o cliente pode passar qualquer fábrica que gere um subtipo do tipo que especificou.
Embora a injeção de dependência melhore a flexibilidade e a facilidade de teste, ela pode ser muito custosa em projetos com muitas dependências. Nesses casos, você pode usar um framework de injeção de dependência (como Dagger, Guice ou Spring) para reduzir o custo.
Comentários0