依存性注入(DI)と制御の反転(IOC)の違い


117

私は依存性注入(DI)と制御の反転(IOC)の多くの参照を見てきましたが、それらの間に違いがあるかどうかは本当にわかりません。

どちらかまたは両方を使い始めたいのですが、それらの違いについて少し混乱しています。


通常、制御の反転は「コンテナ」を指し、依存性注入は実際のパターンを指します。しかし、彼らは手をつないで行きます。Martin Fowlerの記事を読んでこのトピックを理解することをお勧めします。
ベンホフシュタイン

依存性注入はユーザーが行うことであり、Inversion of Controlと呼ばれるコマンド構造につながります。それらは本質的にリンクされています。

2
DIは、IoCの形式ですが、私は中にDIとのIoCのかなり詳細な説明を与えたこの回答

2
DIはIOCの特殊なケースだと思います。従来の制御は、モジュール->モジュールマネージャーからモジュールを要求します。DIでは、モジュールマネージャー->モジュールから要求された依存関係を取得します。
ラファウダウギルド

つまり、基本的にIoCはDIを使用した実装です。私はそれを正しく得ていますか?
dance2die

回答:


53

定義

制御の反転は、アプリケーションフレームワークコードからの具体的な実装の認識を減らし、アプリケーションのドメイン固有のコンポーネントにより多くの制御を与えることを目的とした設計パラダイムです。従来のトップダウン設計のシステムでは、アプリケーションと依存関係の認識の論理的な流れは、最初に設計されたコンポーネントから最後に設計されたコンポーネントに流れます。そのため、制御の反転は、アプリケーションの制御と依存関係の認識のほぼ文字通りの反転です。

依存性注入は、他のクラスが依存するクラスのインスタンスを作成するために使用されるパターンであり、コンパイル時にその機能を提供するためにどの実装が使用されるかを知ることはありません。

一緒に働いている

制御の反転は、特定の機能を提供するコンポーネントを作成するためのメカニズムが必要なため、依存性注入を利用できます。アクティベーター、ファクトリーメソッドなど、他のオプションが存在し、使用されていますが、フレームワーククラスが代わりに必要な依存関係を受け入れることができる場合、フレームワークはこれらのユーティリティクラスを参照する必要はありません。

作業中のこれらの概念の一例は、Reflectorのプラグインフレームワークです。コンパイル時にアプリケーションがプラグインについて何も知らなかったとしても、プラグインはシステムを大きく制御します。これらの各プラグインで1つのメソッドが呼び出されます。メモリが提供される場合は初期化され、プラグインに制御が渡されます。フレームワークは、彼らが何をするのかを知らず、ただやらせるだけです。制御はメインアプリケーションから取得され、特定の作業を実行するコンポーネントに与えられています。制御の反転。

アプリケーションフレームワークでは、さまざまなサービスプロバイダーを介してその機能にアクセスできます。プラグインには、作成時にサービスプロバイダーへの参照が与えられます。これらの依存関係により、プラグインは独自のメニュー項目の追加、ファイルの表示方法の変更、適切なパネルでの独自の情報の表示などを行うことができます。依存関係はインターフェースによって渡されるため、契約が変更されない限り、コード。

当時、構成情報、リフレクション、およびActivatorオブジェクト(少なくとも.NETでは)を使用して、ファクトリメソッドを使用してプラグインを作成していました。現在、アプリケーションフレームワークが依存関係としてプラグインのリストを受け入れる機能を含む依存関係を注入するときに、より広範なオプションを可能にするツール、MEFがあります。

概要

これらの概念は独立して使用および利点を提供できますが、これらを組み合わせることで、はるかに柔軟で再利用可能なテスト可能なコードを作成できます。そのため、これらはオブジェクト指向ソリューションの設計における重要な概念です。


3
いいえ、IoCは古い概念であり、DI(IoCに依存しない)から独立しています。たとえば、Strutsフレームワーク(Java)を取り上げます。これはIoCに大きく依存していますが、DIを使用していません。
ロジェリオ

1
@Rogério-あなたは、2つの概念がお互いを必要としないことを指摘します。答えを更新してそれを明確にし、いくつかのフレームワークがそれらを一緒に使用して、より疎結合のコードを可能にする方法をすばやく説明しました。
チャック

IoCの最も単純なアプリケーションは、おそらくActionListenerです。コードを手続き的に処理する代わりに、イベント処理コードはカスタムコードに委任されます。これにより、コントロールを反転します。
マイク

0

IOCとDIを理解するのに役立つ記事 http://martinfowler.com/articles/injection.html

IOC(制御の反転)

IOCは

  1. インターフェイスへのコーディング(1つのコンポーネントはimplではなく他のコンポーネントのインターフェイスに依存する必要があります)

    interface iComp_2 {...}
    
    class Comp_1 {
        iComp_2 c2 = ….;
    }
    
  2. コンポーネント実装固有のコードの削除

    Comp_1 {
        iComp_2 c2 = getComp_2_Impl(); // not new Comp_2_Impl();
    }
    

IOCは、次のいずれかの方法で実現できます。

1. DI(依存性注入)

3 types of DI

1.1 Constructor Injection

1.2 Setter Injection

1.3 Interface Injection

2.サービスロケーター

DI(依存性注入)コンテナー

コンパイル時ではなく実行時の決定:実行時に、構成ファイルに基づいて使用するインターフェイスの具体的な実装を決定します(したがって、コンパイル時に、どの実装が使用されるかわからないため、アプリケーションの構成可能性が向上します) 。異なるモジュール間の具体的な関係が「実行時」に決定される実装です。

依存性注入後のimplのインスタンス化:implを決定した後、まず(configファイルで指定された)すべての依存性を作成し、次にそれらの依存性をそのimplに注入することにより、そのimplをインスタンス化します。

インスタンスのライフサイクル管理:DIコンテナは通常、ライフサイクルの管理に必要なオブジェクト、またはシングルトンやフライウェイトなどの将来の注入に再利用されるオブジェクトへの参照のみを保持します。コンテナへの呼び出しごとにいくつかのコンポーネントの新しいインスタンスを作成するように設定すると、コンテナは通常、作成されたオブジェクトを忘れます。そうしないと、ガベージコレクターは、使用されなくなったときにこれらのオブジェクトをすべて収集するのに苦労します。


6
「インジェクション」の記事を本当に読みましたか?IOCは、この答えが何を意味するのかではなく、まったくそうではありません。
ロジェリオ

-3

「Inversion of Control」は、すべてのモジュールが抽象的なエンティティと考えられるシステムを設計する方法です。

そして、「依存性注入」は、異なるモジュール間の具体的な関係が「実行時」に決定される実装です。


-4

制御の反転は一般的な概念であり、関数型言語では通常、継続を使用して行われます。これにより、両側が「呼び出し元」であり、「呼び出し先」が存在しないAPIを記述できます。他のより静的な環境では、この機能がないため、制御フローにヒントを挿入するにはこのハックが必要です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.