コンストラクターインジェクションには、依存関係を明示的に示し、クライアントにインスタンスの提供を強制するという利点があります。また、クライアントが後でインスタンスを変更できないことも保証できます。1つの(可能性のある)欠点は、コンストラクターにパラメーターを追加する必要があることです。
Setter Injectionには、コンストラクターにパラメーターを追加する必要がないという利点があります。また、クライアントがインスタンスを設定する必要もありません。これは、オプションの依存関係に役立ちます。これは、たとえばデフォルトで実際のデータリポジトリを作成するクラスが必要な場合にも役立ちます。テストでは、セッターを使用してテストインスタンスに置き換えることができます。
インターフェイスインジェクションは、私が知る限り、セッターインジェクションと大差ありません。どちらの場合も、(オプションで)後で変更できる依存関係を設定しています。
最終的に、それは好みの問題であり、依存関係が必要かどうかです。個人的には、コンストラクター注入をほぼ排他的に使用しています。クライアントにコンストラクターでインスタンスを提供させることにより、クラスの依存関係を明示的にすることが好きです。また、クライアントは事後にインスタンスを変更できないことも気に入っています。
多くの場合、2つの別個の実装を渡す唯一の理由はテストのためです。本番環境ではDataRepository
、に合格するかもしれませんが、テストでは、に合格しますFakeDataRepository
。この場合、通常、2つのコンストラクターを提供します。1つはパラメーターなし、もう1つはを受け入れるコンストラクターですIDataRepository
。次に、パラメーターのないコンストラクターで、2番目のコンストラクターへの呼び出しをチェーンし、aを渡しnew DataRepository()
ます。
C#の例を次に示します。
public class Foo
{
private readonly IDataRepository dataRepository;
public Foo() : this(new DataRepository())
{
}
public Foo(IDataRespository dataRepository)
{
this.dataRepository = dataRepository;
}
}
これは、Poor Man's Dependency Injectionとして知られています。実稼働クライアントコードでは、次のようなステートメントを繰り返して繰り返す必要がないため、気に入っています。
var foo = new Foo(new DataRepository());
ただし、テスト用に別の実装を渡すことはできます。Poor ManのDIでは依存関係をハードコーディングしていることがわかりますが、テストにはほとんどDIを使用しているので、それは受け入れられます。