web-dev-qa-db-ja.com

依存性注入とファクトリーパターン

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

誰かがそれをあなたがそれを使用する方法が違いを生む方法だと言ったなら!

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

誰がそれらの違いとどこで何を使うべきかを教えてもらえますか?

464
Binoj Antony

ファクトリを使用するとき、あなたのコードはまだ実際にオブジェクトを作成する責任があります。 DIによって、あなたはその責任をあなたのコードとは別のクラスまたはフレームワークに外注します。

280

私は概念をわかりやすく単純にしておくことを提案します。依存性注入は、ソフトウェアコンポーネントを疎結合するためのアーキテクチャパターンです。ファクトリパターンは、他のクラスのオブジェクトを作成する責任を別のエンティティに分けるための1つの方法です。ファクトリパターンは、DIを実装するためのツールとして呼び出すことができます。依存性注入は、コンストラクタを使用して、マッピングXMLファイルなどを使用して、DIのように多くの方法で実装できます。

210
Perpetualcoder

依存性注入

部品自体をインスタンス化する代わりに、carが機能する必要がある部品を求めます

class Car
{
    private Engine engine;
    private SteeringWheel wheel;
    private Tires tires;

    public Car(Engine engine, SteeringWheel wheel, Tires tires)
    {
        this.engine = engine;
        this.wheel = wheel;
        this.tires = tires;
    }
}

工場

完全なオブジェクトを作成するためにピースをまとめて配置し、呼び出し元から具体的なタイプを隠します。

static class CarFactory
{
    public ICar BuildCar()
    {
        Engine engine = new Engine();
        SteeringWheel steeringWheel = new SteeringWheel();
        Tires tires = new Tires();
        ICar car = new RaceCar(engine, steeringWheel, tires);
        return car;
    }   
}

結果

ご覧のとおり、工場とDIは互いに補完し合っています。

static void Main()
{
     ICar car = CarFactory.BuildCar();
     // use car
}

あなたはgoldilockと3匹のクマを覚えていますか?さて、依存性注入はそのようなものです。これが同じことをする3つの方法です。

void RaceCar() // example #1
{
    ICar car = CarFactory.BuildCar();
    car.Race();
}

void RaceCar(ICarFactory carFactory) // example #2
{
    ICar car = carFactory.BuildCar();
    car.Race();
}

void RaceCar(ICar car) // example #3
{
    car.Race();
}

例1 - 依存関係を完全に隠してしまうので、これが最悪です。この方法をブラックボックスとして見たのであれば、車が必要だとは思わなかったでしょう。

例2 - 自動車工場を通るので車が必要だとわかっているので、これはもう少し良い方法です。しかし、今回は実際に必要な方法はすべて自動車であるため、あまりにも多くの時間をかけています。車がメソッドの外でビルドされて渡される可能性があるときは、車をビルドするためだけに工場を通過しています。

例#3 - メソッドがを正確に要求するのでこれは理想的です。whatが必要だ。多すぎたり少なすぎません。 MockCarsを作成するためだけにMockCarFactoryを作成する必要はありません。モックを直接渡すことができます。これは直接的で、インターフェイスは嘘をつきません。

Misko HeveryによるこのGoogle Tech Talkは素晴らしいもので、私が私の例を導き出したものの基礎となっています。 http://www.youtube.com/watch?v=XcT4yYu_TTs

169
Despertar

依存関係の注入で解決しやすい問題がありますが、それは一連の工場ではそれほど簡単には解決できないものです。

一方では制御の逆転と依存関係の注入(IOC/DI)と、もう一方ではサービスロケーターまたはファクトリースイート(ファクトリー)との違いは次のとおりです。

IOC/DIは、ドメインオブジェクトとサービス自体の完全なエコシステムです。それはあなたが指定した方法であなたのためにすべてを設定します。あなたのドメインオブジェクトとサービスはコンテナによって構築され、それ自体は構築されません。したがってコンテナやファクトリにはany依存関係はありません。 IOC/DIでは、アプリケーションの最上位層(GUI、Webフロントエンド)のすべての構成を1か所(コンテナの構成)にまとめて、非常に高度な構成設定が可能です。

ファクトリはあなたのドメインオブジェクトとサービスの構築の一部を抽象化します。しかし、ドメインオブジェクトとサービスは、自分自身を構築する方法とそれらが依存するすべてのものを取得する方法を把握する責任があります。これらすべての「アクティブな」依存関係は、アプリケーション内のすべてのレイヤーを介して完全にフィルタリングします。すべてを設定するために行くための単一の場所はありません。

39
yfeldblum

Dependency Injection(DI)とFactory Patternsが似ているのは、それらがソフトウェアアーキテクチャである制御の反転(IoC)の2つの実装であるためです。簡単に言えば、それらは同じ問題に対する2つの解決策です。

質問に答えるために、FactoryパターンとDIの主な違いは、オブジェクト参照がどのように取得されるかです。名前としての依存性注入では、参照が注入されるかコードに与えられることを意味します。 Factoryパターンでは、コードがオブジェクトを取得するように、コードは参照を要求する必要があります。どちらの実装も、コードと、そのコードによって使用されているオブジェクト参照の基本クラスまたは型との間のリンケージを削除または分離します。

実行時に要求されるオブジェクトのタイプまたはクラスに動的に選択またはリンクするために、ファクトリパターン(または実際にはオブジェクト参照を返す新しいファクトリを返すファクトリである抽象ファクトリパターン)を記述できることは注目に値します。これはそれらをIoCの別の実装であるService Locatorパターンに非常に似ています(DIよりさらにもっと)。

Factoryのデザインパターンは(ソフトウェアの観点から)かなり古く、しばらく前からありました。建築パターンIoCの最近の人気以来、それは復活しています。

IoCのデザインパターンになると思います。インジェクタが注入され、ロケータが検出され、工場がリファクタリングされました。

37
Tom Maher

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

24
BinMaster

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

投稿者 http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html

21
Pup

DIは工場の抽象化層の一種だと思いますが、抽象化以外にも利点があります。真のファクトリは単一の型をインスタンス化してそれを設定する方法を知っています。優れたDIレイヤは、設定を通じて、多くのタイプをインスタンス化して設定する機能を提供します。

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

OTOH、実装が頻繁に変わることが予想される多数のタイプを含むプロジェクトがある場合は、DIを使用することで、実行時にファクトリを再コンパイルすることなくこれを実行できる柔軟性が得られます。

16
Will

私はこの質問が古いことを知っています、しかし私は私の5セントを加えたいと思います、

依存性注入(DI)はさまざまな意味で構成可能なファクトリパターン(FP)に似ていると思います。その意味では、DIでできることなら何でもそのようなファクトリでそれを実行できるようになります。

たとえば、Springを使用している場合は、リソースを自動配線(DI)するか、次のようにするかを選択できます。

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

そして、その 'mb'インスタンスを使って何かをします。インスタンスを返すファクトリへの呼び出しではありませんか。

ほとんどのFP例の間で私が気付く唯一の真の違いは、 "myBean"がxmlまたは他のクラスにあるものを設定できることです。フレームワークはファクトリとして機能しますが、それ以外は異なります。同じこと、そしてあなたは確かにconfigファイルを読み込むか、必要に応じて実装を取得するFactoryを持つことができます。

そして、あなたが私の意見を聞いてくれたら(そして私はあなたがそうではなかったことを私は知っています)、私はDIが同じことをするが開発にもっと複雑さを加えると信じます。

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

しかし、...使用しているオブジェクトの実装を知っている必要がないという約束についてはどうでしょうか。ちょっと!真剣に?あなたがこのようなアプローチを使うとき...あなたは実装を書くのと同じではありませんか?そうでなくても、ほとんどの場合、実装がどのように動作するのかを見ているのではありませんか。

そして最後に、DIフレームワークがどの程度約束するかは問題ではありませんあなたはものを構築するでしょう分離された、あなたがそれらのクラスに従属することなくフレームワークを使用しているのであれば、あなたはそれを取り巻くすべてのものを構築していますアプローチやフレームワークを変更する必要がある場合、それは簡単な作業ではありません... EVER! ...心配するのではなく特定のフレームワークがあなたのビジネスのための最善の解決策であるならば、それをするときあなたは大きな問題に直面するでしょう。

実際、私が見ることができる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つの異なるアプリケーションを作成しなければならないことよりも有益ではないでしょうか。

あなたは私に言うことができます、私は今まで実行時にスイッチをする必要はないので、私はアプリを設定します、そして私がクラスを継承するか他の実装を使うなら私はただ設定を変えて再展開します。わかりました、それはまた工場とすることができます。正直言って、あなたはこれを何回やっていますか?社内の他の場所で使用される予定のアプリケーションがあり、そのコードを別のチームに渡す予定がある場合に限って、そのようなことをします。しかし、ちょっと、それはファクトリーでも可能ですし、そしてダイナミックファクトリーでもっと良くなるでしょう!

とにかく、あなたが私を殺すために開いているのであれば、コメント欄は。

12
Frank Orellana

理論

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

  1. 誰がオブジェクトを作成します

    • [ファクトリ]:HOWオブジェクトを作成する必要があります。作成ロジックを含む独立したFactoryクラスがあります。
    • [依存性注入]:実際には、外部のフレームワークによって行われます(たとえば、Javaではspring/ejb/guiceなど)。新しいオブジェクトを厳密に作成することなく、「魔法のように」注入が行われます。
  2. 管理するオブジェクトの種類

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

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

  1. 私たちが作りたいもの

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

  1. 建築

次のようなレイヤアーキテクチャを作りたいとしましょう。

enter image description here

ドメインオブジェクトは、データベース内に格納されているオブジェクトです。リポジトリ(DAO)はデータベースからのオブジェクトのretrievevarを手助けします。サービスは他のモジュールにAPIを提供します。 orderモジュールに対する操作が許可されています

  1. ドメイン層と工場の利用

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

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

しかし、OrderLinesについての知識がなくてもOrderを作成する方法は?

工場

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

enter image description here

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

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

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

enter image description here

12
Marcin Szymczak

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

6
Thakur

依存性注入では、クライアントは自分自身で依存性を取得する必要はなく、すべて事前に準備されています。

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

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

しかし工場では、このようなオブジェクトが必要な場所にこの1行を書く必要があります。 DIを使用すると、配線(使用法と作成されたオブジェクトとの関係)を一度作成するだけで済み、その後はどこでもそのオブジェクトの存在に依存するだけで済みます。反対に、DIは準備面でもう少し(フレームワークに依存する程度)作業を必要とすることがよくあります。

5
Kosi2801

実際の例では、2つの(およびその他の)アプローチの比較については、 このリンク を参照してください。

基本的に、要件が変更されたときに、DIの代わりにファクトリを使用すると、より多くのコードを修正することになります。

これは手動のDIでも有効です(つまり、オブジェクトへの依存関係を提供する外部フレームワークがない場合は、各コンストラクタで渡します)。

私がDIについて読んでこの記事にたどり着くとすぐに私は同じ質問をしました。だから最後にこれは私が理解したものですが間違っているなら私を訂正してください。

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

小さな王国の統治体は「工場」です。

大きな政府は「依存性注入器」です。

3
blueskin

私は、DIがBeanを構成またはインスタンス化する方法であると考えています。 DIは、コンストラクター、セッター - ゲッターなどのさまざまな方法で実行できます。

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

このリンクをチェックしてください。 依存性注入

2
harshit

ビノイ、

私はあなたが他を選ぶ必要があるとは思わない。

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

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

2
Jason Slocomb

私は、3つの重要な側面がオブジェクトとその使用法を左右すると信じています。
1。 インスタンス化(もしあれば初期化と一緒のクラスの)。
2。 インジェクション(そのように作成されたインスタンスの)必要な場所。
3。 ライフサイクル管理(そのように作成されたインスタンスの)。

ファクトリー・パターンを使用すると、最初の側面(インスタンス化)は達成されますが、残りの2つは疑問です。他のインスタンスを使用するクラスは、(インスタンスを作成するのではなく)ファクトリをハードコードしなければならず、これが疎結合能力を妨げることになります。さらに、ファクトリが複数の場所で使用されている大きなアプリケーションでは、インスタンスのライフサイクル管理(特に、ファクトリが返すインスタンスのライフサイクルを管理していない場合は難しくなります)醜い)。

一方、(IoCパターンの)DIを使用すると、3つすべてがコードの外側(DIコンテナー)に抽象化され、マネージドBeanはこの複雑さについて何も必要としません。 疎結合、非常に重要なアーキテクチャ上の目標は、静かに快適に達成することができます。もう1つの重要なアーキテクチャ上の目標である懸念の分離は、工場よりもはるかに優れた目標を達成することができます。

工場は小規模な用途に適しているかもしれませんが、大規模な工場は工場よりもDIを選択するほうが良いでしょう。

2
Anand Vemula

ここでのほとんどの回答は、両者の概念的な違いと実装の詳細を説明しています。しかし、IMOが最も重要で、OPが尋ねたアプリケーションの違いについての説明を見つけることができませんでした。それでは、このトピックをもう一度開きましょう。

誰かがそれをあなたがそれを使用する方法が違いを生む方法だと言ったなら!

その通りです。 90%の場合、FactoryかDIのどちらかを使用してオブジェクト参照を取得できますが、通常は後者になります。他の10%のケースではFactoryを使用しています正しい方法のみ。このような場合には、実行時パラメータで変数によってオブジェクトを取得することが含まれます。このような:

IWebClient client = factoryWithCache.GetWebClient(url: "stackoverflow.com",
        useCookies: false, connectionTimeout: 120);

この場合、DIからclientを取得することはできません(または少なくとも醜い回避策が必要です)。したがって、決定を下すための一般的な規則として、実行時に計算されたパラメータがなくても依存関係を取得できる場合はDIが優先され、それ以外の場合はFactoryが使用されます。

1
neleus

ファクトリーデザインパターン

工場デザインパターンは、

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

あなたが以下のようにあなた自身を質問するときあなたはいくつかのことを観察することができます

  • ファクトリはインプリメンテーションクラス用のオブジェクトをいつ作成しますか - 実行時またはコンパイル時?
  • 実行時に実装を切り替えたい場合はどうしますか? - できません

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

依存性注入

依存関係を注入する方法はいくつかあります。簡単にするためにInterface Injectionを使いましょう。

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

したがって、静的インスタンス化は不要です。

例:

public class MyClass{

  MyInterface find= null;

  //Constructor- During the object instantiation

  public MyClass(MyInterface myInterface ) {

       find = myInterface ;
  }

  public void myMethod(){

       find.doSomething();

  }
}

ファクトリでは、関連するインタフェースをグループ化することができます。そのため、渡されたパラメータをファクトリにまとめることができれば、constructor overinjectionのための良い解決策になります*)。

public AddressModelFactory(IAddressAttributeService addressAttributeService,
        IAddressAttributeParser addressAttributeParser,
        ILocalizationService localizationService,
        IStateProvinceService stateProvinceService,
        IAddressAttributeFormatter addressAttributeFormatter)
    {
        this._addressAttributeService = addressAttributeService;
        this._addressAttributeParser = addressAttributeParser;
        this._localizationService = localizationService;
        this._stateProvinceService = stateProvinceService;
        this._addressAttributeFormatter = addressAttributeFormatter;
    }

コンストラクタを見てください、あなたはそこにIAddressModelFactoryを渡す必要があるので、より少ないパラメータ*):

 public CustomerController(IAddressModelFactory addressModelFactory,
        ICustomerModelFactory customerModelFactory,
        IAuthenticationService authenticationService,
        DateTimeSettings dateTimeSettings,
        TaxSettings taxSettings,
        ILocalizationService localizationService,
        IWorkContext workContext,
        IStoreContext storeContext,
        ICustomerService customerService,
        ICustomerAttributeParser customerAttributeParser,
        ICustomerAttributeService customerAttributeService,
        IGenericAttributeService genericAttributeService,
        ICustomerRegistrationService customerRegistrationService,
        ITaxService taxService,
        CustomerSettings customerSettings,
        AddressSettings addressSettings,...

CustomerControllerには渡されたたくさんのパラメータがあります。はい、これはconstructor overinjectionと見ることができますが、これはDIの仕組みです。 CustomerControllerに問題がないことはありません。

*)コードはnopCommerceからのものです。

1

私の考え:

依存性注入:共同作業者をパラメータとしてコンストラクタに渡します。依存性注入フレームワーク:コンストラクタにパラメータとして渡すオブジェクトを作成するための一般的で設定可能なファクトリ。

1
bloparod

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

それはすべてあなたの要求次第です。アプリケーションにファクトリパターンを実装する必要がある場合は、無数のインジェクションフレームワーク実装の1つによって要件が満たされる可能性が高いです。

あなたの要件がどのサードパーティのフレームワークでも満たすことができない場合にのみ、あなたはあなた自身のソリューションを展開すべきです。より多くのコードを書くほど、より多くのコードを保守する必要があります。コードは資産ではなく負債です。

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

1
Mick

額面から見ると同じです

非常に簡単な言葉では、ファクトリパターン、創造的パターンは私たちにオブジェクトを作成するのを助けます - 「オブジェクトを作成するためのインターフェースを定義する」。キー値の種類のオブジェクトプール(たとえば、Dictionary)があり、そのキーをファクトリに渡すと(私は単純ファクトリパターンを参照しています)、Typeを解決できます。仕事は終わった!一方、依存性注入フレームワーク(Structure Map、Ninject、Unityなど)も同じことをしているようです。

しかし……「車輪を再発明しないでください」

建築的見地からは、その拘束力のある層と「車輪の再発明をしない」。

エンタープライズグレードのアプリケーションでは、DIの概念は依存関係を定義するアーキテクチャー層です。これをさらに簡単にするために、依存関係を解決する別のクラスライブラリプロジェクトとしてこれを考えることができます。主なアプリケーションは、Dependency resolverが他の具体的な実装および依存関係の解決を指すこのプロジェクトに依存しています。

Factoryからの "GetType/Create"に加えて、ほとんどの場合私たちはもっと多くの機能(依存関係を定義するためにXMLを使用する能力、モック、そして単体テストなど)を必要とします。構造マップを参照したので、 構造マップ機能リスト を見てください。単純なオブジェクトマッピングを単に解決するだけではありません。車輪を再発明しないでください。

あなたが持っているのがハンマーだけであれば、すべてが釘のように見えます

あなたの要求とあなたがどのタイプのアプリケーションを構築するかに応じて、あなたは選択をする必要があります。プロジェクトの数が少なく(1つか2つの場合もあります)、依存関係がほとんどない場合は、より簡単な方法を選択できます。これは、単純な1または2のデータベース呼び出しにEntity Frameworkを使用してADO .Netデータアクセスを使用するのと同じです。このシナリオでは、EFの導入はやり過ぎです。

しかし、大規模プロジェクトの場合、またはプロジェクトが大きくなる場合は、フレームワークを含むDIレイヤーを用意し、使用するDIフレームワークを変更する余地を確保することを強くお勧めします。 ..等。)。

1
Dhanuka777

簡単に言うと、Dependency Injection vs Factoryの方法はそれぞれPush vs pullのメカニズムを意味します。

Pull mechanism:classは間接的にFactory Methodに依存しており、Factory Methodは具象クラスに依存しています。

プッシュメカニズム:ルートコンポーネントはすべての依存コンポーネントで1つの場所に設定できるため、高度なメンテナンスと疎結合を促進します。

Factoryメソッドでは、依存性注入と同様に責任が外部委託されている(ただし抽象化のリークを犠牲にして)場合でも、(間接的ではあるが)クラスの責任はクラスにあります。

0
Rahul Agarwal

これらは直交しており、一緒に使用できると思います。私が最近仕事で出会った例をお見せしましょう。

DIにはJavaのSpringフレームワークを使用していました。シングルトンクラス(Parent)は別のクラス(Child)の新しいオブジェクトをインスタンス化しなければなりませんでした、そしてそれらは複雑な共同作業者を持っていました:

@Component
class Parent {
    // ...
    @Autowired
    Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) {
        this.dep1 = dep1;
        this.dep2 = dep2;
    }

    void method(int p) {
        Child c = new Child(dep1, dep2, ..., depN, p);
        // ...
    }
}

この例では、Parentは、DepXコンストラクタに渡すためだけにChildインスタンスを受け取る必要があります。これに関する問題:

  1. Parentは必要以上にChildの知識が豊富です
  2. Parentには必要以上に共同編集者がいます
  3. Childに依存関係を追加するには、Parentを変更する必要があります

私はFactoryが完全にここに収まることに気付いたときです。

  1. Childに見られるように、それはParentクラスの本当のパラメータ以外のすべてを隠します。
  2. これはChildを作成するための知識をカプセル化したもので、DI構成に集中させることができます。

これは簡略化されたParentクラスとChildFactoryクラスです。

@Component
class Parent {
    // ...
    @Autowired
    Parent(ChildFactory childFactory) {
        this.childFactory = childFactory;
    }

    void method(int p) {
        Child c = childFactory.newChild(p);
        // ...
    }
}

@Component
class ChildFactory {
    // ...
    @Autowired
    Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) {
        this.dep1 = dep1;
        this.dep2 = dep2;
        // ...
        this.depN = depN;
    }

    Child newChild(int p) {
        return new Child(dep1, dep2, ..., depN, p);
    }
}
0
Martín Coll