5 に答える
コンポーネントをどのようにリンクするかが重要です。たとえば、上記では、パーサーを必要とするクラスにパーサーを挿入することを期待しています。例えば
それ以外の:
public class MyParserUsingClass {
...
public MyParserUsingClass() {
this.parser = new Parser();
}
}
あなたがするだろう:
public class MyParserUsingClass {
...
public MyParserUsingClass(Parser injectedParser) {
this.parser = injectedParser;
}
}
なぜこれを行うのですか?パーサーを使用するクラスは、パーサーがどこから来たのかをあまり気にせず、実際には具体的なインスタンスではなくインターフェイスを使用する必要があります。パーサーを注入することにより、状況に応じてさまざまなインスタンスを提供したり、テスト用にモックアウトしたりできます。そうしないと、クラスが内部的に作成するだけで、制御できなくなります。これは、構成可能なコンポーネント、ネットワークを介して通信するコンポーネント、重量のあるコンポーネントなどにとって特に重要です。
ジョブが と呼ぶクラスがあるとしましょうMyCustomParser
。ここで、そのクラスにパーサーを注入して、注入するパーサーのタイプに対して異なる動作を取得できるようにする必要があります (json は変更される可能性があり、別の方法で解析したいなど)。したがって、(インスタンスによって) 呼び出されるメソッドを使用してInterface
-を作成する必要
があります。これで、解析の方法に応じて、このメソッドのさまざまな実装を使用できます。必要なのは、このインターフェイスを使用するクラスに渡すことだけです (コンストラクターでパラメーターとして渡すこともできます)。この場合、クラスにパーサーを注入していますIParser
ParseIt
MyCustomParser
MyCustomParser
あなたの特定の例では、依存性注入は次のようになります。
public class MyParser {
private final JsonParser parser;
public MyParser(JsonParser parser) {
this.parser = parser;
}
public Result parse(JsonInput input) {
Result = parser.parse(input);
}
}
それがインターフェースであると仮定すると、使用する特定の実装に依存しないJsonParser
、そのインターフェースの任意の実装を提供できるようになりました。MyParser
厳密な意味での依存性注入は、クラスのインポートやクラスパスへの jar ファイルの追加とは何の関係もありません。インターフェイスの原則へのプログラミングをサポートするためのものであり、制御の反転の形式です。
これがもたらす主な利点は、コードが明示的な依存関係の実装に依存せず、代わりに抽象化を使用することです。あなたはインターフェースに依存しており、そのインターフェースの実装クラスのいくつかのインスタンスは、実行時にクラスに「注入」されます(コンストラクターパラメーター、セッター、または-私の意見では、悪い選択-インスタンスフィールドとして)。
結果として、たとえば、サービス クラスは一部の DAO/リポジトリ インターフェイスのみを考慮し、内部で異なる実装を提供するため、サービス コンポーネントのコードに触れることなく永続化レイヤーを変更できます。
依存性注入とは、クラスがそれ自体に依存するもののインスタンスを作成する必要があるインスタンスを減らすことです。
依存性注入は、代わりに、外部メカニズムを介して消費クラスにそれらの依存性を「与える」ことを目的としています。一般的なメソッドには、コンストラクターを介して依存関係を渡すことや、クラスのパブリックに「設定可能な」プロパティに依存関係を設定することが含まれます。
たとえば、コンストラクターを介した依存性注入は次のようになります。
public class Parser
{
private IJsonParser parser;
public Parser(IJsonParser parser) {
this.parser = parser;
}
}
これにより、Parserクラスが次のようなことを行う必要がなくなります。
public class Parser
{
private IJsonParser parser;
public Parser() {
this.parser = new JsonParser();
}
}
これは、単一責任の原則に基づいています-パーサークラスはJsonParserの作成に責任を持つ必要はなく、使用する特定のJsonParserを気にする必要もありません-懸念されるのは、IJsonParserによって指定された作業を実行する何かが必要なことです。インターフェイスを作成し、より高度な制御コードに任せて、その作業を行うのに最適な適切な具象タイプを決定します。