[アイテム5]リソースを直接指定するのではなく、依存オブジェクト注入を使用する


  • 多くのクラスは、1つまたは複数のリソースに依存し、例えば、スペルチェックは、予め定められたクラスに依存し、これらのクラスは、通常、静的ユーティリティクラスとして実装される.
    // 정적 유틸리티를 잘못 사용한 예
    public class SpellChecker {
    		private static final Lexicon dictionary = ...;
    
    		private SpellChecker() {} // 객체 생성 방지
    
    		public static boolean isValid(String word) { ... }
    		public static List<String> suggetstions(String type) { ... }
    }
  • 単転実施もよく見られる
  • // 정적 유틸리티를 잘못 사용한 예
    public class SpellChecker {
    		private final Lexicon dictionary = ...;
    
    		private SpellChecker() {} // 객체 생성 방지
    		public static SpellChecker INSTANCE = new SpellChecker(...);
    
    		public boolean isValid(String word) { ... }
    		public List<String> suggetstions(String type) { ... }
    }

  • 以上の2つの方法が1冊の辞書しか使われていないとすれば、あまり良い方法ではありません.

  • 1冊の辞書ですべての使い方に対応できるのは純粋な対応です

  • 静的ユーティリティクラスまたはシングルクラスは、使用するリソースに応じて動作を変更するクラスには適用されません.

  • インスタンスを作成するときに、作成者に必要なリソースを渡す方法があります.これは、スペルチェッカーを作成するときに依存オブジェクトに辞書を注入する依存オブジェクト注入の形式です.
  • public class SpellChecker {
    		private final Lexicon dictionary;
    		
    		public SpellChecker(Lexicon dictionary) {
    				this.dictionary = Objects.requireNonNull(dictionary);
    		}
    	
    		public boolean isValid(String word) { ... }
    		public List<String> suggestions(String typo) { ... }
    }

  • これは、1つのリソースdictionaryのみを使用する依存オブジェクト注入モードの1つの方法であるが、どれだけのリソースがあっても、依存関係にかかわらず、うまく動作する.

  • また、(同じリソースを使用しようとする)複数のクライアントが、依存するオブジェクトを安心して共有できることを保証します.

  • 依存オブジェクト注入は、作成者、静的ファクトリ、コンストラクタにも適用されます.

  • 「ファクトリメソッド」モデルの実装から、リソースファクトリを作成者に移行するまで
  • Supplier<T>インタフェースは、完全なファクトリの例です.

  • Supplierインタフェースは、任意のタイプのサブタイプのファクトリを作成できます.

  • これは、オブジェクトが呼び出されるたびに特定のタイプのインスタンスを繰り返し作成することを意味し、Supplierインタフェースがファクトリを表す完璧な例であるファクトリメソッドモードを実現します.
  • Supplier<T>を入力する方法は、通常、工場のタイプパラメータを制限するために限られたワイルドカードタイプを使用する必要があり、これにより、クライアントは生成可能なタイプのサブタイプをスキップすることができる.
  • 限定されたワイルドカードのタイプは?
    ワイルドカードの種類の制限
    ここで、ワイルドカードは、汎用コードの?であり、未知のタイプである.
    したがって、この限定されたワイルドカードタイプによって、ファクトリのタイプパラメータを制限することができます.
    この方法では、クライアントは作成可能な任意のタイプのサブタイプのファクトリをスキップできます.
    Mosaic create(Supplier<? extends Tile> tileFactory) { ... }
    名前の通り、パラメータを制限するために限られたワイルドカードタイプが使用されているため、すべてのタイプが独自のサブタイプであると考えられる.

  • 依存オブジェクトを注入すると柔軟性とテストの使いやすさが向上しますが、依存オブジェクトが数千個ある場合はコードが乱れます.

  • Dagger、Guice、Springなどの依存オブジェクト注入フレームワークを使用すると、このような混乱を解消できます.これらのフレームワークで使用されるAPIは、依存オブジェクトを直接注入するのに非常に適しています.