540

依存性注入の使用法として引用されている例のほとんどは、ファクトリ パターンを使用して解決することもできます。使用法/設計に関しては、依存性注入と工場の違いがぼやけているか薄いようです。

誰かが私に、それをどのように使用するかが違いを生むと言ったことがあります!

私は以前、 StructureMapを DI コンテナーとして使用して問題を解決しましたが、後で単純なファクトリで動作するように再設計し、StructureMap への参照を削除しました。

それらの違いと、どこで何を使用するか、ここでのベストプラクティスは何ですか?

4

30 に答える 30

307

ファクトリを使用する場合でも、コードはオブジェクトの作成を実際に担当します。DI によって、その責任をコードとは別の別のクラスまたはフレームワークに外注します。

于 2009-02-17T17:14:02.433 に答える
235

概念を単純明快にすることをお勧めします。依存性注入は、ソフトウェア コンポーネントを疎結合するためのアーキテクチャ パターンに近いものです。ファクトリ パターンは、他のクラスのオブジェクトを作成する責任を別のエンティティに分離する 1 つの方法にすぎません。ファクトリパターンは、DI を実装するためのツールとして呼び出すことができます。依存性注入は、コンストラクターを使用した DI やマッピング xml ファイルを使用したなど、さまざまな方法で実装できます。

于 2009-02-17T17:10:28.777 に答える
27

DI の欠点の 1 つは、オブジェクトをロジックで初期化できないことです。たとえば、名前と年齢がランダムなキャラクターを作成する必要がある場合、ファクトリー パターンよりも DI を選択することはできません。ファクトリを使用すると、オブジェクトの作成からランダム アルゴリズムを簡単にカプセル化できます。これは、「変化するものをカプセル化する」と呼ばれる設計パターンの 1 つをサポートします。

于 2012-05-01T09:24:19.357 に答える
22

ライフサイクル管理は、インスタンス化と注入に加えて、依存関係コンテナーが引き受ける責任の 1 つです。インスタンス化後にコンテナがコンポーネントへの参照を保持することがあるという事実が、コンテナがファクトリではなく「コンテナ」と呼ばれる理由です。依存性注入コンテナーは通常、ライフサイクルを管理する必要があるか、シングルトンやフライウェイトなどの将来の注入に再利用されるオブジェクトへの参照のみを保持します。コンテナーへの呼び出しごとにいくつかのコンポーネントの新しいインスタンスを作成するように構成されている場合、コンテナーは通常、作成されたオブジェクトを単に忘れます。

から: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html

于 2010-12-20T20:09:28.193 に答える
17

仮説

考慮すべき重要な点が 2 つあります。

  1. オブジェクトの作成者

    • [Factory]: オブジェクトをどのように作成するかを記述する必要があります。作成ロジックを含む別の Factory クラスがあります。
    • [依存性注入]: 実際には、外部フレームワークによって行われます (たとえば、Java では spring/ejb/guice になります)。インジェクションは、新しいオブジェクトを明示的に作成しなくても「魔法のように」発生します
  2. 管理するオブジェクトの種類:

    • [ファクトリ]: 通常、ステートフル オブジェクトの作成を担当します。
    • [依存性注入] ステートレス オブジェクトを作成する可能性が高くなります

単一のプロジェクトでファクトリと依存性注入の両方を使用する方法の実際の例

  1. 私たちが構築したいもの

orderline と呼ばれる複数のエントリを含む注文を作成するためのアプリケーション モジュール。

  1. 建築

次のレイヤー アーキテクチャを作成するとします。

ここに画像の説明を入力

ドメイン オブジェクトは、データベース内に格納されているオブジェクトである場合があります。リポジトリ (DAO) は、データベースからのオブジェクトの取得に役立ちます。サービスは、他のモジュールに API を提供します。orderモジュールの操作を許可します

  1. ドメイン層とファクトリの使用法

データベースに含まれるエンティティは、Order と OrderLine です。注文は複数の OrderLines を持つことができます。 Order と OrderLine の関係

次に重要な設計部分です。これ以外のモジュールは独自に OrderLines を作成および管理する必要がありますか? いいえ。注文明細は、注文が関連付けられている場合にのみ存在する必要があります。内部実装を外部クラスに隠すことができれば最高です。

しかし、OrderLines に関する知識がなくても注文を作成するにはどうすればよいでしょうか?

工場

新しい注文を作成したい人は、OrderFactory を使用しました (これにより、注文の作成方法に関する詳細が隠されます)。

ここに画像の説明を入力

それがIDE内でどのように見えるかです。domainパッケージ外のクラスOrderFactoryは、内部のコンストラクターの代わりに使用されますOrder

  1. 依存性注入 依存性注入は、リポジトリやサービスなどのステートレス レイヤーでより一般的に使用されます。

OrderRepository と OrderService は、依存性注入フレームワークによって管理されます。リポジトリは、データベースでの CRUD 操作の管理を担当します。サービスはリポジトリを挿入し、それを使用して正しいドメイン クラスを保存/検索します。

ここに画像の説明を入力

于 2017-05-29T12:59:27.787 に答える
16

DI はファクトリの抽象化レイヤーの一種だと思いますが、DI は抽象化を超えた利点も提供します。真のファクトリは、単一のタイプをインスタンス化して構成する方法を知っています。優れた DI レイヤーは、構成を通じて、多くの型をインスタンス化および構成する機能を提供します。

明らかに、構造に比較的安定したビジネス ロジックを必要とするいくつかの単純な型を持つプロジェクトの場合、ファクトリ パターンは理解しやすく、実装しやすく、うまく機能します。

OTOH、実装が頻繁に変更されることが予想される多数のタイプを含むプロジェクトがある場合、DI は、工場を再コンパイルすることなく、実行時にこれを行うための構成を通じて柔軟性を提供します。

于 2009-02-17T17:13:04.323 に答える
13

この質問が古いことは承知していますが、5 セント追加したいと思います。

依存性注入 (DI) は多くの点で、構成可能なファクトリー パターン (FP) に似ていると思います。その意味で、DI でできることはすべて、そのようなファクトリーでもできるようになります。

実際、たとえばSpringを使用する場合、自動配線リソース(DI)または次のようなオプションがあります。

MyBean mb = ctx.getBean("myBean");

そして、その「mb」インスタンスを使用して何かを行います。インスタンスを返すファクトリの呼び出しではありませんか??

ほとんどの FP の例で気付いた唯一の実際の違いは、「myBean」が xml または別のクラスにあるものを構成でき、フレームワークがファクトリとして機能することですが、それ以外は同じことです。確かに、構成ファイルを読み取るか、必要に応じて実装を取得する Factory を持つことができます。

そして、私の意見を求められた場合 (そして、あなたがそうしなかったことは知っています)、DI は同じことを行うと思いますが、開発をより複雑にするだけです。なぜですか?

まず、DI で自動配線する Bean に使用されている実装を知るには、構成自体に移動する必要があります。

しかし...使用しているオブジェクトの実装を知る必要がないという約束はどうですか? ふふっ!真剣に?このようなアプローチを使用すると...実装を書くのと同じではありませんか?? そうでない場合でも、ほとんどの場合、実装が本来の目的をどのように実行するかを確認していませんか??

最後にもう 1 つ、DI フレームワークが、クラスに依存することなく、DI フレームワークから切り離されたものを構築することをどれだけ約束してもかまいません。フレームワークを使用している場合は、その周りにすべてを構築します。アプローチやフレームワークを変更するのは簡単なことではありません...決して!...しかし、ビジネスにとって何が最善の解決策であるかを心配するのではなく、その特定のフレームワークを中心にすべてを構築するため、それを行うときに大きな問題に直面することになります。

実際、私が見ることができる唯一の FP または DI アプローチの実際のビジネス アプリケーションは、実行時に使用されている実装を変更する必要がある場合ですが、少なくとも私が知っているフレームワークではそれを行うことができません。開発時の構成ではすべてが完璧であり、必要に応じて別のアプローチを使用します。

したがって、同じアプリケーション内の 2 つのスコープで異なるパフォーマンスを示すクラスがある場合 (たとえば、持ち株会社の 2 つの会社)、2 つの異なる Bean を作成するようにフレームワークを構成し、それぞれを使用するようにコードを調整する必要があります。次のように書くのと同じではないでしょうか。

MyBean mb = MyBeanForEntreprise1(); //In the classes of the first enterprise
MyBean mb = MyBeanForEntreprise2(); //In the classes of the second enterprise

これと同じ:

@Autowired MyBean mbForEnterprise1; //In the classes of the first enterprise
@Autowired MyBean mbForEnterprise2; //In the classes of the second enterprise

この:

MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise1"); //In the classes of the first enterprise
MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise2"); //In the classes of the second enterprise

いずれにせよ、クラスであれ構成ファイルであれ、アプリケーションで何かを変更する必要がありますが、それを再デプロイする必要があります。

次のようなことをするのはいいことではないでしょうか:

MyBean mb = (MyBean)MyFactory.get("mb"); 

そして、そのようにして、ログに記録されたユーザーエンタープライズに応じて、実行時に適切な実装を取得するようにファクトリのコードを設定しますか?? 今それは役に立ちます。新しいクラスを含む新しい jar を追加し、実行時にルールを設定することもできます (または、このオプションを開いたままにする場合は新しい構成ファイルを追加します)。既存のクラスを変更する必要はありません。これは動的工場になります。

これは、企業ごとに 2 つの構成を作成し、それぞれに 2 つの異なるアプリケーションを用意するよりも便利ではないでしょうか??

実行時に切り替えを行う必要がないので、アプリを構成し、クラスを継承するか別の実装を使用する場合は、構成を変更して再デプロイするだけです。わかりました、それは工場でも行うことができます。正直に言うと、これを何回やりますか?社内の別の場所で使用する予定のアプリがあり、そのコードを別のチームに渡し、彼らがこのようなことを行う場合にのみ使用できます。でもねえ、それはファクトリーでもできますし、動的ファクトリーならもっといいでしょう!!

とにかく、あなたが私を殺すために開いているなら、コメントセクション。

于 2012-09-13T05:02:57.967 に答える
6

IOC は、2 つの方法で実装される概念です。依存関係の作成と依存関係の注入、ファクトリ/抽象ファクトリは、依存関係の作成の例です。依存性注入は、コンストラクター、セッター、およびインターフェースです。IOC の核心は、具体的なクラスに依存するのではなく、メソッドの抽象 (インターフェイス/抽象クラスなど) を定義し、その抽象を使用して具体的なクラスのメソッドを呼び出すことです。Factory パターンと同様に、基本クラスまたはインターフェイスを返します。同様に、依存性注入では、基本クラス/インターフェイスを使用してオブジェクトの値を設定します。

于 2011-08-28T08:22:42.247 に答える
4

依存性注入を使用すると、クライアントは依存性を独自に取得する必要がなく、すべて事前に準備されます。

ファクトリでは、誰かがそれらを呼び出して、生成されたオブジェクトを必要な場所に移動する必要があります。

違いは主に、ファクトリの呼び出しと構築されたオブジェクトのフェッチが行われるこの 1 行にあります。

しかし、ファクトリでは、そのようなオブジェクトが必要なすべての場所にこの 1 行を書かなければなりません。DI を使用すると、ワイヤリング (使用法と作成されたオブジェクトの関係) を一度作成するだけで、その後はどこでもオブジェクトの存在に依存するだけです。一方、DI では、準備側でもう少し多くの作業 (フレームワークによって異なります) が必要になることがよくあります。

于 2009-02-17T17:12:34.200 に答える
3

DIについて読んですぐに同じ質問があり、この投稿にたどり着きました. 最終的にこれは私が理解したものですが、間違っている場合は修正してください。

「ずっと前に、独自の統治機関が独自の書面による規則に基づいて管理および決定を下す小さな王国がありました。その後、一連の規則(憲法)を持ち、裁判所を通じて実施されるこれらの小さな統治機関をすべて排除する大きな政府を形成しました。」

小さな王国の統治体は「ファクトリー」

大きな政府は「依存性インジェクター」です。

于 2010-12-20T22:23:43.110 に答える
2

DI は、Bean を構成またはインスタンス化する方法だと思います。DI は、コンストラクター、setter-getter など、さまざまな方法で実行できます。

ファクトリ パターンは、Bean をインスタンス化するもう 1 つの方法です。このパターンは、ファクトリ デザイン パターンを使用してオブジェクトを作成する必要がある場合に主に使用されます。このパターンを使用している間は、Bean のプロパティを構成せず、オブジェクトをインスタンス化するだけだからです。

このリンクを確認してください:依存性注入

于 2009-02-17T18:01:17.190 に答える
2

ビノジ、

どちらかを選ぶ必要はないと思います。

依存クラスまたはインターフェイスをクラス コンストラクターまたはセッターに移動する操作は、DI パターンに従います。コンストラクターまたはセットに渡すオブジェクトは、Factory で実装できます。

いつ使う?開発者の操舵室にあるパターンを使用します。彼らが最も快適に感じ、最も理解しやすいと感じるものは何ですか。

于 2009-02-17T19:02:07.887 に答える
2

私は、3 つの重要な側面がオブジェクトとその使用法を管理していると考えて
ます。 2.必要な場所への (そのように作成されたインスタンスの)インジェクション。 3. (作成されたインスタンスの)ライフサイクル管理。 Factory パターンを使用すると、最初の側面 (インスタンス化) は達成されますが、残りの 2 つは疑問です。他のインスタンスを使用するクラスは、(インスタンスを作成する代わりに)ファクトリをハードコーディングする必要があり、疎結合機能を妨げます。また、ライフサイクルマネジメント



ファクトリが複数の場所で使用される大規模なアプリケーションでは、インスタンスの数が課題になります (特に、ファクトリが返すインスタンスのライフ サイクルを管理していない場合、見苦しくなります)。

一方、(IoC パターンの) DI を使用すると、3 つすべてがコードの外側で (DI コンテナーに) 抽象化され、マネージド Bean はこの複雑さについて何も必要としません。ルーズ カップリングは、非常に重要な建築目標であり、静かで快適に達成できます。もう 1 つの重要なアーキテクチャ上の目標である、関心の分離は、ファクトリよりもはるかに優れた方法で実現できます。

ファクトリは小規模なアプリケーションに適しているかもしれませんが、大規模なアプリケーションにはファクトリよりも DI を選択する方が適しています。

于 2017-04-28T05:24:19.707 に答える
1

私の考え:

依存性注入: コラボレーターをパラメーターとしてコンストラクターに渡します。依存性注入フレームワーク: コンストラクターにパラメーターとして渡すオブジェクトを作成するための汎用的で構成可能なファクトリ。

于 2009-10-28T01:22:39.863 に答える
1

インジェクション フレームワークは、Factory パターンの実装です。

それはすべてあなたの要件に依存します。アプリケーションにファクトリ パターンを実装する必要がある場合、無数に存在するインジェクション フレームワークの実装の 1 つによって要件が満たされる可能性が非常に高くなります。

要件がサードパーティのフレームワークのいずれでも満たせない場合にのみ、独自のソリューションを展開する必要があります。書くコードが増えるほど、維持しなければならないコードも増えます。コードは資産ではなく負債です。

どの実装を使用する必要があるかについての議論は、アプリケーションのアーキテクチャのニーズを理解することほど根本的に重要ではありません。

于 2013-06-17T02:23:11.207 に答える
1

工場設計パターン

ファクトリーデザインパターンの特徴は

  • インターフェイス
  • 実装クラス
  • 工房

以下のように自問自答すると、いくつかのことが観察できます

  • ファクトリが実装クラスのオブジェクトを作成するのはいつですか?実行時またはコンパイル時?
  • 実行時に実装を切り替えたい場合はどうしますか? -不可

これらは、依存性注入によって処理されます。

依存性注入

依存関係を注入するには、さまざまな方法があります。簡単にするために、インターフェイス注入を使用しましょう

DI では、コンテナは必要なインスタンスを作成し、それらをオブジェクトに「注入」します。

したがって、静的なインスタンス化がなくなります。

例:

public class MyClass{

  MyInterface find= null;

  //Constructor- During the object instantiation

  public MyClass(MyInterface myInterface ) {

       find = myInterface ;
  }

  public void myMethod(){

       find.doSomething();

  }
}
于 2014-09-24T08:20:35.970 に答える
-4

私の意見では、次のような場合は依存性注入を使用する方がはるかに優れています。 1. コードを小さなパーティションにデプロイする。2. テスト容易性は、分離されていないオブジェクトを簡単にモックできるため、DI を使用しても問題ないケースの 1 つです。インターフェイスを使用すると、各オブジェクトを簡単にモックおよびテストできます。3. ゆるやかに分離されているため、プログラムの他の部分をコーディングする必要なく、プログラムの各部分を同時に修正できます。

于 2014-12-22T19:21:33.563 に答える