1

次のクラス階層が与えられた場合

  • ClassAにはClassBが必要
  • ClassBにはClassCが必要

次のような依存関係グラフを取得します。

ClassA --> ClassB --> ClassC

したがって、DI を使用する場合、ClassC を ClassB に、ClassB を ClassA に注入します。

しかし、ClassC が実行時の依存関係 (たとえば、ある種の戦略) であるとしましょう。実行時の依存関係を注入する方法として提案されているのは、

ClassCFactory

これで、ClassCFactory を ClassB に注入して、次のグラフを取得できます

ClassA --> ClassB --> ClassCFactory

これで ClassB にメソッドができました。このメソッドを呼び出して、ファクトリに作業を行わせることができます。例えば

ObjB.SelectC(MyRuntimeValue)

しかし、今回のアプリケーションでは、ClassB について何も知りません (おそらく、さらにいくつかの層が関係しています)。解決策の 1 つは、ClassA に SelectC を配置することです。

ObjA.SelectC(MyRuntimeValue) -(calls)-> ObjB.SelectC(MyRuntimeValue)

または、単にデメテルの法則に違反して、次のようなことを行います

ObjA.ObjB.SelectC(MyRuntimeValue) 

2 番目の解決策が適切ではないことは誰もが認めると思います。しかし、最初の解決策にはいくつかの欠点もあります。特に、中間層が多い場合はなおさらです。

ファクトリを 1 レベル引き上げて ClassB を作成することもできますが、ClassB は本当に実行時の依存関係なのでしょうか? どのような解決策を提案しますか? それとも、クラスの設計が悪いのでしょうか?

私見は、必要なオブジェクトを作成するファクトリではなく、オブジェクトが実際に作業を行うために必要なものに依存することを常にお勧めします。しかし、この考えを念頭に置いて、DIコンテナは役に立たないでしょう...

4

2 に答える 2

2

ランタイム依存関係を注入する提案された方法は、抽象ファクトリを導入することです

実行時に何かを注入するために必ずしも抽象ファクトリが必要なわけではありません。セッター注入またはメソッド注入を使用して、単純な依存関係をオブジェクトに直接渡すことができます。

抽象ファクトリは、一連の関連するオブジェクトファミリからオブジェクトを生成する必要があるが、どのファミリが実行時までわからない場合のオプションになります。あなたの例では、これが事実であることを示していないため、YAGNI/KISS は使用しないことを示します。

しかし、今回のアプリケーションでは、ClassB について何も知りません (おそらく、さらにいくつかの層が関係しています)。

あなたのシナリオでこれが当てはまる理由について詳細を教えてください。私には、ClassB を認識し、C を挿入できるある種の実行コンテキストが常に存在するようです。ただし、ClassB を A に注入する実行コンテキストと同じである必要はありません。

IoC は、ハリウッドの原則としても知られてい"Don't call us, we'll call you"ます。それが誰で"we"、いつその"call you"部分が行われるかは、アプリケーションによって大きく異なります。厳格なルールはありません。ObjectA が ClassC について知りすぎているのではないかと心配している場合は、その注入を他の誰かに委任してください。DI コンテナーは、その点で大いに役立ちます。

于 2013-03-26T10:18:20.943 に答える