3[Item 5]-リソースではなく依存オブジェクト注入を使用


多くのクラスは、1つ以上のリソースに依存する場合があります.
次の2つの例では、SpellChecker機能を持つクラスがDictionaryというユーティリティクラスを使用すると仮定します.

(1)スタティックユーティリティの使用

public class SpellChecker{
	private static final Lexicon dictionary = ...;
    
    // 인스턴스화 방지
    private SpellChecker(){} 
    
    public static boolean isValid(String word) {...}
    public static List<String> suggestions(String typo) {...}
}

SpellChecker.isValid(word);

(2)Singletonの使用

public class SpellChecker {
	private final Lexicon dictionary = ...;
    
     // 인스턴스화 방지
    private SpellChecker() {}
    public static SpellChecker INSTANCE = new SpellChecker(...);
    
    public boolean isVaild(String word) {...}
    public List<String> suggestions(String typo) {...}
}

SpellChecker.INSTANCE.isValid(word);
以上の2つの使い方はいずれもdictionaryのコードが1つしかないと仮定している点があまりよく見えません.
辞書は異なる言語で分けることもできるし、特殊な語彙の辞書で分けることもできるからだ.
では、どのようにして柔軟なSpellCheckerを作成しますか?
  • dictionaryフィールドからfinal限定子を削除しsetterを作成する方法
    -->マルチスレッド環境では使用できません.静的ユーティリティクラスまたは単一インスタンスクラスは、使用するリソースに応じて変化するクラスには適用されません.
  • インスタンスを作成するときに、作成者に必要なリソースを渡す方法
    -->依存オブジェクトを注入する形式で,依存オブジェクト辞書を注入すればよい.
  • (3)注入依存対象

  • は、柔軟性、再利用性、およびテスト性を向上させることができる.
  • リソースがいくらであれ、依存関係にかかわらず、SpellCheckerという機能は正常に動作します.注入されたdictionaryは変わらないので、複数のクライアントがこれらの依存オブジェクトを安心して共有することができます.
  • public class SpellChecker{
    	private final Lexicon dictionary;
        
        public SpellChecker(Lexcion dictionary){
        	this.dictionary = Objects.requireNotNull(dictionary);
        }
        
        public static boolean isValid(String word){...};
    }  
      
    このモードの変形により,リソースファクトリをジェネレータに渡す方法がある.
    Factoryとは、呼び出すたびに特定のタイプのインスタンスを繰り返し作成するオブジェクトです.すなわち,工場メソッドモデルを実現した.
    Supplierインタフェースは工場を表現する完璧な例である.入力としてSupplierを受け入れる方法は、通常、工場のタイプパラメータを制限するために、限定ワイルドカードタイプ(境界付きワイルドカードタイプ)を使用する必要がある.
    このようにして、クライアントは任意のタイプのサブタイプをスキップして、任意のタイプのファクトリを作成することができます.
    たとえば、次のコードは、クライアントが提供する工場で作成したタイルからなるモザイクを作成する方法です.
    Mosaic create(Supplier<? extends Tile> tileFactory> { ... }
    注入依存オブジェクトの柔軟性とテストの使いやすさを向上させることができますが、依存性が数千個に達する大規模なプロジェクトでは、コードも混乱します.
    このような混乱を解消するには、dagger、Guice、Springなどの依存オブジェクト注入フレームワークを使用します.
    これは、これらのフレームワークが、依存オブジェクトを直接注入するために設計されたAPIを使用することを意味する.