コンストラクターに、必要なクラスの新しいインスタンスを作成させるのと、新しいクラスに必要な参照を渡すのとでは、どちらが良いのでしょうか、それとも悪いのでしょうか?
つまり、基本的には次の違いです。
A classA = new A();
B classB = new B(classA);
また、クラスAをそのフィールド/プロパティに割り当てるクラスBコンストラクタがあります。
と比べて:
B classB = new B();
そして
public class B{
A classA {private set; get;}
//constructor
public B(){
classA = new A();
}
}
後者の例は、作成および割り当て以降、単一の責任に違反しますか?プログラマーが知らないことをしているという点で、これはあまりにも多くの魔法ですか?コンストラクタはそれを行うべきですか?
コンストラクターは、定期的に他のオブジェクトを作成します。一部の言語では、それは避けられないものです。たとえば、C++では、コンストラクターが新しいオブジェクトのすべてのメンバーオブジェクトを構築します。
ですから、それ自体は良くも悪くもありません。それは意味論に依存します:
A
がB
を存続させることを意図している場合、new B()
は適切なオプションではありません。2番目のアプローチの主な問題は、テストが非常に難しいことです。
ClassAの特定の動作を検証するテストを作成する場合、それは常にClassBに依存しています。 ClassAのコンストラクターでClassBを作成した場合、それを制御することはできません。 ClassAがいくつかの条件付き作業を行うためにClassBのプロパティFooを読み取る場合、さまざまなケースをどのようにチェックしますか?テストをセットアップする簡単な方法はありません。つまり、Fooプロパティを必要な値に設定します。
代わりにClassBをClassAのコンストラクターに注入すると、突然、はるかに単純になります。テストでは、ClassBのインスタンスを作成し、Fooの値を指定し、ClassAのインスタンスを作成して、正しい動作を確認できます。テストが完了しました。他のFoo値について繰り返します...
このパターンは依存性注入と呼ばれ、他のアプローチよりも優先されるはずです。コンストラクターで直接クラスを構築する場合の依存関係は、副作用を引き起こし、テストを困難にするため、アンチパターンです。