Esta é uma postagem traduzida por IA.
Selecionar idioma
Texto resumido pela IA durumis
- Se uma classe depender internamente de um ou mais recursos, é melhor não usar classes de utilitário estáticas e classes singleton, e é preferível usar a injeção de dependência.
- O uso da injeção de dependência pode melhorar a flexibilidade, reusabilidade e facilidade de teste da classe, e os recursos podem ser injetados por meio do construtor, fábrica estática, construtor, etc.
- A injeção de dependência pode ser usada passando o próprio recurso ou uma fábrica de recursos, e o uso de um framework de injeção de dependência é eficiente para projetos com muitas dependências.
Se uma classe internamente depender de um ou mais recursos e esses recursos influenciarem o comportamento da classe, é recomendável não usar singletons e classes de utilitários estáticas.
Esses recursos não devem ser criados diretamente pela classe, mas sim passados para o construtor quando necessários. A injeção de dependências pode melhorar a flexibilidade, reutilizabilidade e facilidade de teste da classe.
Exemplo
Exemplo de uso de classe de utilitários estáticos
public class SpellChecker {
private static final Lexicon dictionary = new Lexicon();
private SpellChecker() {
}
public static boolean isValid(String word) {
// Lógica usando o dicionário
}
public static List suggestions(String typo) {
// Lógica usando o dicionário
}
Supõe-se que essa classe de utilitários usa apenas um dicionário. No entanto, na realidade, os dicionários podem ser separados por idioma e até mesmo dicionários separados podem ser usados para vocabulário especial.
Exemplo de uso de classe singleton
public class SpellChecker {
private final Lexicon dictionary = new Lexicon();
public static SpellChecker INSTANCE = new SpellChecker();
private SpellChecker() {
}
public static boolean isValid(String word) {
// Lógica usando o dicionário
}
public static List suggestions(String typo) {
// Lógica usando o dicionário
}
As classes singleton também assumem que usam apenas um dicionário, portanto, têm as mesmas desvantagens.
Solução 1 - Remova a palavra-chave final do campo
public class SpellChecker {
private Lexicon dictionary = new Lexicon();
public static SpellChecker INSTANCE = new SpellChecker();
private SpellChecker() {
}
public static void changeDictionary(Lexicon dictionary) {
this.dictionary = dictionary;
}
public static boolean isValid(String word) {
// Lógica usando o dicionário
}
public static List suggestions(String typo) {
// Lógica usando o dicionário
}
Você também pode remover a palavra-chave final do dicionário em classes de utilitários estáticas ou classes singleton e projetar o código para que o dicionário possa ser substituído por outro dicionário externo. No entanto, esse método é complicado de usar e pode causar problemas de simultaneidade em ambientes multithread.
Solução 2 - Use injeção de dependência
public class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary) {
this.dictionary = dictionary;
}
public static boolean isValid(String word) {
// Lógica usando o dicionário
}
public static List suggestions(String typo) {
// Lógica usando o dicionário
}
Através deste exemplo, podemos perceber que as classes estáticas e singleton não devem depender de recursos internos. Ou seja, é recomendável injetar os recursos externos.
As classes que usam injeção de dependência têm a vantagem de garantir a imutabilidade graças à palavra-chave final, e também suportam várias 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 fábricas estáticas e construtores.
A injeção de dependência pode simplesmente passar o próprio recurso ou passar uma fábrica de recursos, que é frequentemente usada. Uma fábrica é um objeto que cria repetidamente uma instância de um determinado tipo quando chamada. Esse método é chamado de padrão de método de fábrica, e o Supplier
public static List create(Supplier extends Car> generator) {
...
Geralmente, o tipo de parâmetro de uma fábrica é restrito usando um tipo de curinga limitado. Com esse método, o cliente pode passar qualquer fábrica que seja um subtipo do tipo especificado.
A injeção de dependência melhora a flexibilidade e a facilidade de teste, mas pode ser bastante cara em projetos com muitas dependências. Nesse caso, você pode usar uma estrutura de injeção de dependência (Dagger, Guice, Spring etc.) para reduzir os custos.