![translation](https://cdn.durumis.com/common/trans.png)
Questo è un post tradotto da IA.
[Effettivi Java] Elemento 5. Non dichiarare risorse, utilizzare l'iniezione di dipendenze
- Lingua di scrittura: Coreana
- •
-
Paese di riferimento: Tutti i paesi
- •
- Tecnologia dell'informazione
Seleziona la lingua
Testo riassunto dall'intelligenza artificiale durumis
- Se una classe dipende internamente da una o più risorse, è meglio non utilizzare classi di utilità statiche o classi singleton, ma utilizzare l'iniezione di dipendenze.
- L'utilizzo dell'iniezione di dipendenze può migliorare la flessibilità, la riusabilità e la facilità di test della classe e le risorse possono essere iniettate tramite costruttori, fabbriche statiche, builder, ecc.
- L'iniezione di dipendenze può essere utilizzata passando la risorsa stessa o una fabbrica di risorse, e per i progetti con molte dipendenze, è efficiente utilizzare un framework di dipendenze.
Se si scopre che una classe dipende internamente da una o più risorse e che tali risorse influenzano il comportamento della classe, è preferibile non utilizzare classi di utilità statiche o singleton.
Non dovresti nemmeno far sì che la classe crei queste risorse direttamente. Piuttosto, è preferibile passare le risorse necessarie al costruttore. L'iniezione di dipendenze può migliorare la flessibilità, la riusabilità e la facilità di test della classe.
Esempio
Esempio di utilizzo di una classe di utilità statica
public class SpellChecker {
private static final Lexicon dictionary = new Lexicon();
private SpellChecker() {
}
public static boolean isValid(String word) {
// logica che utilizza il dizionario
}
public static List suggestions(String typo) {
// logica che utilizza il dizionario
}
Questa classe di utilità presuppone che venga utilizzato un solo dizionario. Tuttavia, in realtà, i dizionari possono essere diversi a seconda della lingua e, a volte, è possibile avere un dizionario separato per vocaboli speciali.
Esempio di utilizzo di una 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) {
// logica che utilizza il dizionario
}
public static List suggestions(String typo) {
// logica che utilizza il dizionario
}
Anche la classe singleton presuppone che venga utilizzato un solo dizionario, quindi si verificano gli stessi svantaggi di cui sopra.
Soluzione 1 - Rimuovere la parola chiave final dal 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) {
// logica che utilizza il dizionario
}
public static List suggestions(String typo) {
// logica che utilizza il dizionario
}
È possibile rimuovere la parola chiave final dal dizionario della classe di utilità statica o singleton e consentire al codice esterno di sostituire il dizionario con un dizionario diverso. Tuttavia, questo metodo è scomodo da usare e può causare problemi di concorrenza in un ambiente multi-thread.
Soluzione 2 - Utilizzare l'iniezione di dipendenze.
public class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary) {
this.dictionary = dictionary;
}
public static boolean isValid(String word) {
// logica che utilizza il dizionario
}
public static List suggestions(String typo) {
// logica che utilizza il dizionario
}
Tramite l'esempio precedente, possiamo capire che le classi statiche e le classi singleton non dovrebbero dipendere da risorse interne. Ciò significa che è preferibile iniettare risorse esterne.
La classe che utilizza l'iniezione di dipendenze garantisce l'immutabilità grazie alla parola chiave final e offre il vantaggio di supportare più istanze di risorse. Inoltre, l'iniezione di dipendenze può essere applicata non solo al costruttore, ma anche alle fabbriche statiche e ai costruttori.
L'iniezione di dipendenze non si limita a passare la risorsa stessa, ma spesso si usa anche il metodo di passaggio della factory della risorsa. Una factory è un oggetto che crea ripetutamente istanze di un determinato tipo quando viene chiamato. Questo metodo è chiamato pattern factory method e Supplier
public static List create(Supplier extends Car> generator) {
...
Di solito, un tipo di carattere jolly limitato viene utilizzato per limitare il parametro di tipo della factory. Utilizzando questo metodo, il client può passare qualsiasi factory che sia un sottotipo del tipo specificato dal client.
L'iniezione di dipendenze migliora la flessibilità e la facilità di test, ma può essere costosa per progetti con un'elevata dipendenza. In questi casi, è possibile utilizzare un framework di iniezione di dipendenze (Dagger, Guice, Spring, ecc.) per ridurre i costi.