Martin Fowlerによる論文 によれば、制御の逆転はプログラムの制御フローが逆転する原則です。プログラマーがプログラムのフローを制御する代わりに、外部ソース(フレームワーク、サービス、他のコンポーネントはそれを制御します。何か他のものにつなぐようなものです。彼はEJB 2.0に関する例を挙げました。
例えば、Session Beanインターフェースは、ejbRemove、ejbPassivate(2次ストレージに保管)、およびejbActivate(受動状態から復元)を定義します。これらのメソッドがいつ呼び出されるのかを制御することはできません。コンテナは私たちを呼び出します、私たちはそれを呼び出しません。
これはフレームワークとライブラリの違いにつながります。
コントロールの反転は、フレームワークをライブラリとは異なるものにする重要な部分です。ライブラリは基本的にあなたが呼ぶことができる関数の集合です。最近では通常クラスにまとめられています。各呼び出しはいくつかの作業を行い、クライアントに制御を返します。
私は、DIがIOCであるという見方は、オブジェクトの依存関係が逆になっていることを意味します。代わりに、それはそれ自身の依存関係、ライフサイクルを制御します。しかし、あなたが手でDIについて私に言ったように、DIは必ずしもIOCではありません。私たちはまだDIを持つことができ、IOCはありません。
ただし、この文書では(pococapsuleから、C/C++用の別のIOC Framework)、IOCとDIのためにIOCコンテナとJ2EEはフレームワークコードをコンポーネントに組み込んでいるため、DIフレームワークはJ2EEよりはるかに優れているため、プレーンJava/C++オブジェクト(POJO/POCO)にはなりません。
Dependency Injectionパターン以外のコントロールコンテナの反転 (アーカイブリンク)
上記の2番目の論文につながる、古いコンポーネントベース開発フレームワークの問題は何かを理解するための追加の読み: なぜInversion of Control (アーカイブリンク)
私の質問:IOCとDIは正確に何ですか。私は混乱しています。 pococapsuleに基づくと、IOCは、単にオブジェクトやプログラマとフレームワークの間の制御を逆転させるよりも重要です。
IoC アプリケーションにフレームワーク内のメソッドを呼び出させるのではなく、フレームワークがアプリケーションによって提供される実装を呼び出すことを意味する一般的な用語です。
DI はIoCの形式です。実装はコンストラクタ/セッター/サービスルックアップを介してオブジェクトに渡され、オブジェクトは正しく動作するために「依存」します。
DIを使用しないIoC たとえば、実装はサブクラス化によってのみ変更できるため、テンプレートパターンになります。
DIフレームワーク DIを利用するように設計されており、実装を簡単に渡すことができるようにインターフェース(またはJavaのAnnotations)を定義できます。
IoC Containers プログラミング言語の外でも動作できるDIフレームワークです。侵略的ではないメタデータファイル(XMLなど)でどの実装を使用するかを設定できます。一部の人では、 pointcuts に実装をインジェクトするのと同じように通常は不可能であるIoCを実行できます。
この Martin Fowlerの記事 も参照してください。
要するに、IoCはDIを含むがこれに限定されないもっと広い意味の用語です。
制御の反転(IoC)という用語はもともと、全体的なフレームワークまたはランタイムがプログラムフローを制御する、あらゆる種類のプログラミングスタイルを意味していました。
DIが登場する前は、Dependenciesを管理するフレームワークをInversion of Control Containersと呼んでいましたが、間もなく、IoCの意味が徐々にその特定の意味、つまりDependenciesに対するInversionの制御に向かってドリフトしました。
コントロールの反転 (IoC)は、オブジェクトが自分の作業を行うことに依存している他のオブジェクトを作成しないことを意味します。代わりに、外部のソースから必要なオブジェクトを取得します(たとえば、xml設定ファイル)。
依存性注入 (DI)は、これがオブジェクトの介入なしに、通常はコンストラクターパラメーターを渡してプロパティを設定するフレームワークコンポーネントによって行われることを意味します。
DIはIoCのサブセットです
IoC ( _ i _ nversion o f _ c _ ontrol): - これは総称であり、いくつかの方法で実装されています(イベント) 、代表者など)。
_ di _ ( _ d _ ependency _ i _ njection): - DIはIoCのサブタイプで、コンストラクター注入)によって実装されます。 、セッター注入またはインターフェース注入。
しかし、Springは次の2種類しかサポートしていません。
NullPointerException: bean does not exist
を取得します。コンストラクタ注入は、依存関係を注入するためのベストプラクティスです。IOC(コントローラの反転) :オブジェクトのインスタンスを取得するためにコンテナに制御を渡すことを制御の反転と呼びます。コンテナはあなたのためにそれをします。
DI(依存性注入) :オブジェクトにプロパティを注入する方法は、依存性注入と呼ばれます。
We have three types of Dependency injection
1) Constructor Injection
2) Setter/Getter Injection
3) Interface Injection
Springはコンストラクタインジェクションとセッター/ゲッターインジェクションのみをサポートします。
すべての答えは理論を重視しているので、最初のアプローチの例を使って説明します。
注文が出荷されたらSMS確認メッセージを送信する機能を含むアプリケーションを構築しているとします。 2つのクラスがあります。1つはSMS(SMSService)の送信を担当し、もう1つはユーザー入力のキャプチャを担当(UIHandler)します。コードは次のようになります。
public class SMSService
{
public void SendSMS(string mobileNumber, string body)
{
SendSMSUsingGateway(mobileNumber, body);
}
private void SendSMSUsingGateway(string mobileNumber, string body)
{
/*implementation for sending SMS using gateway*/
}
}
public class UIHandler
{
public void SendConfirmationMsg(string mobileNumber)
{
SMSService _SMSService = new SMSService();
_SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
}
}
上記の実装は問題ではありませんが、いくつか問題があります。
- )開発環境で、これを達成するためにSMS gatewayを使用する代わりにテキストファイルに送信されたSMSを保存したいとします。 (SMSService)の具体的な実装を別の実装に変更することになります。この場合、柔軟性を失い、コードの書き換えを余儀なくされます。
- )クラスの責任を混在させることになります。(UIHandler)は(SMSService)の具体的な実装について決して知っているべきではありません。これは「Interfaces」を使用してクラスの外で行う必要があります。これが実装されると、同じインターフェースを実装する別のモックサービスで使用される(SMSService)を交換することでシステムの動作を変更することができます。このサービスはmobileNumberに送信する代わりにSMSをテキストファイルに保存します。
上記の問題を解決するために、(SMSService)と新しい(MockSMSService)によって実装されるインタフェースを使用します。基本的に新しいインタフェース(ISMSService)は、以下のコードと同じ両方のサービスの動作を公開します。
public interface ISMSService
{
void SendSMS(string phoneNumber, string body);
}
それから、(SMSService)実装を(ISMSService)インターフェースを実装するように変更します。
public class SMSService : ISMSService
{
public void SendSMS(string mobileNumber, string body)
{
SendSMSUsingGateway(mobileNumber, body);
}
private void SendSMSUsingGateway(string mobileNumber, string body)
{
/*implementation for sending SMS using gateway*/
Console.WriteLine("Sending SMS using gateway to mobile:
{0}. SMS body: {1}", mobileNumber, body);
}
}
これで、同じインターフェースを使用して、まったく異なる実装で新しいモックアップサービス(MockSMSService)を作成できるようになります。
public class MockSMSService :ISMSService
{
public void SendSMS(string phoneNumber, string body)
{
SaveSMSToFile(phoneNumber,body);
}
private void SaveSMSToFile(string mobileNumber, string body)
{
/*implementation for saving SMS to a file*/
Console.WriteLine("Mocking SMS using file to mobile:
{0}. SMS body: {1}", mobileNumber, body);
}
}
この時点で、(UIHandler)のコードを変更して、サービスの具体的な実装(MockSMSService)を次のように簡単に使用できます。
public class UIHandler
{
public void SendConfirmationMsg(string mobileNumber)
{
ISMSService _SMSService = new MockSMSService();
_SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
}
}
私たちは、コード内で多くの柔軟性を実現し、関心事の分離を実装しましたが、それでも2つのSMSサービスを切り替えるためにコードベースを変更する必要があります。したがって、 Dependency Injection を実装する必要があります。
これを実現するには、依存関係を渡すための(UIHandler)クラスコンストラクターへの変更を実装する必要があります。これにより、(UIHandler)を使用するコードで、使用する(ISMSService)の具体的な実装を決定できます。
public class UIHandler
{
private readonly ISMSService _SMSService;
public UIHandler(ISMSService SMSService)
{
_SMSService = SMSService;
}
public void SendConfirmationMsg(string mobileNumber)
{
_SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
}
}
クラスと対話するUIフォーム(UIHandler)は、どの実装のインターフェース(ISMSService)を使用するかを渡す必要があります。これは、コントロールを逆にしたことを意味します。(UIHandler)は、どの実装を使用するかを決定する責任を負いません。呼び出しコードは実行します。 制御の反転 の原則を実装しました。これはDIがその一種です。
UIフォームコードは以下のようになります。
class Program
{
static void Main(string[] args)
{
ISMSService _SMSService = new MockSMSService(); // dependency
UIHandler _UIHandler = new UIHandler(_SMSService);
_UIHandler.SendConfirmationMsg("96279544480");
Console.ReadLine();
}
}
IoC - コントロールの反転は一般的な用語で、言語には関係なく、実際にはオブジェクトを作成するのではなく、どのような方法でオブジェクトが作成されているのかを記述します。
_ di _ - 依存性注入とは具体的な用語で、実行時にさまざまな注入技術を使用してオブジェクトの依存関係を提供します。セッター注入、コンストラクター注入、またはインターフェース注入による。
しかし、春のドキュメンテーションはそれらが同じであると言います。
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-introduction
最初の行では、 " IoCは依存性注入(DI) "としても知られています。
制御の反転は、アプリケーションの対象となるコンポーネント、つまり作業を完了させるコンポーネントをより制御することを目的とした設計パラダイムです。
依存性注入は、コンパイル時にどのクラスがその機能を提供するために使用されるのかを知らずに他のオブジェクトが依存するオブジェクトのインスタンスを作成するために使用されるパターンです。
制御の反転を実装するための基本的な手法がいくつかあります。これらは:
制御の反転は、保守が容易な再利用可能なモジュール式ソフトウェアフレームワークの作成を支援するソフトウェアアーキテクチャの一般的な設計原則です。
それは、制御の流れが一般的に書かれたライブラリまたは再利用可能なコードから「受け取られる」という設計原則です。
理解を深めるために、コーディングの初期の頃のコーディング方法を見てみましょう。手続き型/伝統的言語では、ビジネスロジックは一般にアプリケーションのフローを制御し、一般的なまたは再利用可能なコード/関数を「呼び出し」ます。たとえば、単純なコンソールアプリケーションでは、私の制御の流れは私のプログラムの指示によって制御されます。これには、一般的な再利用可能な機能への呼び出しが含まれる場合があります。
print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);
//More print and scan statements
<Do Something Interesting>
//Call a Library function to find the age (common code)
print Age
対照的に、IoCでは、フレームワークはビジネスロジックを「呼び出す」再利用可能なコードです。
たとえば、Windowsベースのシステムでは、ボタン、メニュー、ウィンドウ、ダイアログボックスなどのUI要素を作成するためのフレームワークがすでに利用可能になります。私が自分のアプリケーションのビジネスロジックを書くとき、私のビジネスロジックコードを呼び出すのはフレームワークのイベントであり(イベントが発生したとき)、その逆ではありません。
フレームワークのコードは私のビジネスロジックを認識していませんが、それでも私のコードを呼び出す方法を知っているでしょう。これは、イベント/デリゲート、コールバックなどを使用して実現されます。ここではフローの制御は「反転」です。
そのため、静的にバインドされたオブジェクトに対する制御の流れに依存するのではなく、その流れはオブジェクトグラフ全体および異なるオブジェクト間の関係に依存します。
依存性注入は、オブジェクトの依存性を解決するためのIoC原則を実装した設計パターンです。
簡単に言うと、コードを書き込もうとすると、さまざまなクラスを作成して使用することになります。 1つのクラス(クラスA)が他のクラス(クラスBおよび/またはD)を使用することがあります。したがって、クラスBとDはクラスAの依存関係です。
簡単な例えはCarクラスです。車はエンジン、タイヤなどのような他のクラスに依存するかもしれません。
Dependency Injectionは、その依存関係(Class Engineとclass Tire)を作成するDependentクラス(ここではClass Car)の代わりに、依存関係の具体的なインスタンスをクラスに注入する必要があることを示唆しています。
もっと実用的な例で理解しましょう。あなたがあなた自身のTextEditorを書いていると考えてください。とりわけ、あなたは彼のテキストの中のタイプミスをチェックする機能をユーザに提供するスペルチェッカを持つことができます。そのようなコードの単純な実装は次のようになります。
Class TextEditor
{
//Lot of rocket science to create the Editor goes here
EnglishSpellChecker objSpellCheck;
String text;
public void TextEditor()
{
objSpellCheck = new EnglishSpellChecker();
}
public ArrayList <typos> CheckSpellings()
{
//return Typos;
}
}
一見すると、すべてがバラ色に見えます。ユーザーがテキストを書くでしょう。開発者はテキストをキャプチャしてCheckSpellings関数を呼び出し、ユーザーに表示するTyposのリストを見つけます。
1人のユーザーがエディターでフランス語を書き始める1つのすばらしい日まで、すべてがうまく機能するようです。
より多くの言語のサポートを提供するためには、より多くのSpellCheckersが必要です。おそらくフランス語、ドイツ語、スペイン語など.
ここでは、 "English" SpellCheckerがTextEditorクラスと緊密に結合された密結合コードを作成しました。つまり、TextEditorクラスはEnglishSpellCheckerに依存している、つまりEnglishSpellChekerはTextEditorの依存関係です。この依存関係を取り除く必要があります。さらに、テキストエディタには、実行時に開発者の判断に基づいてスペルチェッカーの具体的な参照を保持する方法が必要です。
したがって、DIの紹介で見たように、クラスにはその依存関係を注入する必要があることがわかります。したがって、すべての依存関係を呼び出されたクラス/コードに注入するのは、呼び出し側のコードの責任です。そのため、コードを次のように再構築できます。
interface ISpellChecker
{
Arraylist<typos> CheckSpelling(string Text);
}
Class EnglishSpellChecker : ISpellChecker
{
public override Arraylist<typos> CheckSpelling(string Text)
{
//All Magic goes here.
}
}
Class FrenchSpellChecker : ISpellChecker
{
public override Arraylist<typos> CheckSpelling(string Text)
{
//All Magic goes here.
}
}
この例では、TextEditorクラスはISpellChecker型の具象インスタンスを受け取ります。
これで、依存関係はコンストラクタ、パブリックプロパティ、またはメソッドに挿入できます。
コンストラクタDIを使用してクラスを変更してみましょう。変更されたTextEditorクラスは次のようになります。
Class TextEditor
{
ISpellChecker objSpellChecker;
string Text;
public void TextEditor(ISpellChecker objSC)
{
objSpellChecker = objSC;
}
public ArrayList <typos> CheckSpellings()
{
return objSpellChecker.CheckSpelling();
}
}
そのため、呼び出し元のコードは、テキストエディタの作成中に、適切なSpellCheckerタイプをTextEditorのインスタンスに挿入できます。
あなたは完全な記事を読むことができます ここ
_ ioc _ はアプリケーションのクラスを管理する外部クラスを意味し、外部クラスはアプリケーションのクラス間の依存関係をコンテナが管理することを意味します。 _ ioc _ の基本的な概念は、プログラマがあなたのオブジェクトを作成する必要はなく、それらがどのように作成されるべきかを記述することです。
IoCコンテナによって実行される主なタスクは以下のとおりです。 アプリケーションクラスをインスタンス化する。オブジェクトを設定します。オブジェクト間の依存関係を組み立てます。
_ di _ は、実行時にセッターインジェクションまたはコンストラクターインジェクションを使用してオブジェクトの依存関係を提供するプロセスです。
DIおよびIOCは2つdesign pattern 主にコンポーネント間の疎結合を提供することに重点を置いているか、オブジェクト同士が緊密にならないようにオブジェクト間の従来の依存関係を切り離す単純な方法。
次の例で、これらの概念の両方を説明しようとしています。
以前は、このようなコードを書いていました
Public MyClass{
DependentClass dependentObject
/*
At somewhere in our code we need to instantiate
the object with new operator inorder to use it or perform some method.
*/
dependentObject= new DependentClass();
dependentObject.someMethod();
}
依存性注入では、依存性インジェクターがオブジェクトのインスタンス化を処理します
Public MyClass{
/* Dependency injector will instantiate object*/
DependentClass dependentObject
/*
At somewhere in our code we perform some method.
The process of instantiation will be handled by the dependency injector
*/
dependentObject.someMethod();
}
インスタンス化とインジェクションのために他のいくつかのコントロール(コンテナなど)に制御を与える上記のプロセスは、Inversion of Controlと呼ばれ、IOCコンテナが依存関係をインジェクトするプロセスと呼ばれます。依存性注入として。
IOCは、プログラムの制御フローが反転する原理です。プログラマーがプログラムのフローを制御する代わりに、、プログラムはプログラマーへのオーバーヘッドを減らすことでフローを制御します.and依存関係を注入するためにプログラムが使用するプロセスは、DI
この2つの概念は連携して動作し、より柔軟で再利用可能なカプセル化されたコードを記述する方法を提供します。これにより、オブジェクト指向ソリューションの設計における重要な概念となります。
また読むことをお勧めします。
ここで私の同様の答えの1つを確認することもできます
IOC(Inversion of Control)は、基本的に依存関係を除去し、それらをフローを非線形にするように分離する設計パターンの概念であり、コンテナまたは他のエンティティに依存関係のプロビジョニングを管理させる。それは実際にはハリウッドの校長に従います「私たちを呼ばないでください私たちはあなたを呼び出します」。その違いをまとめます。
制御の逆転: - 依存関係を分離し、それらのプロビジョニングを委任することは一般的な用語です。これはいくつかの方法で実装できます(イベント、デリゲートなど)。
依存性注入: - DIはIOCのサブタイプで、コンストラクター注入、セッター注入、またはメソッド注入によって実装されます。
次の記事ではこれについて非常に詳しく説明しています。
https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO
IOC(Inversion Of Control): オブジェクトのインスタンスを取得するためにコンテナに制御を渡すことを、制御の反転と呼びます。 new演算子 を使用してオブジェクトを作成しているのではなく、コンテナにそれを実行させてください。
DI(依存性注入): (POJOクラスで)XMLから必要なパラメータ(プロパティ)をオブジェクトに渡すことは、依存性注入と呼ばれます。
// ICO、DI、10年前、これは彼らのやり方でした:
public class AuditDAOImpl implements Audit{
//dependency
AuditDAO auditDAO = null;
//Control of the AuditDAO is with AuditDAOImpl because its creating the object
public AuditDAOImpl () {
this.auditDAO = new AuditDAO ();
}
}
今では3、4またはそれ以降の最新のバージョンでは以下のようになっています。
public class AuditDAOImpl implements Audit{
//dependency
//Now control is shifted to Spring. Container find the object and provide it.
@Autowired
AuditDAO auditDAO = null;
}
全体的な制御は、オブジェクトを利用可能にするSpringのようなフレームワークへの結合されたコードの古い概念から逆にされます。だから私が知る限りではIOCで、コンストラクタやセッターを使って他のオブジェクトに依存オブジェクトをインジェクトするときに知っているようにDependencyインジェクション。注入は基本的にそれを引数として渡すことを意味します。春には、XMLオブジェクトとアノテーションベースの設定を使用して、Beanオブジェクトを定義し、依存オブジェクトをコンストラクタまたはセッターインジェクションスタイルで渡します。
IoCの概念は、手続き型プログラミング時代に最初に聞かれました。そのため、IoCは歴史的な文脈から、control-flowすなわち、関数を希望する順序で呼び出す責任を誰が持っているか-関数自体であるか、それを何らかの外部エンティティに反転させる必要があるかどうか。
しかし、いったんOOPが出現すると、人々はOOPコンテキストでIoCについて話し始めました。ここでは、アプリケーションは、制御フローとは別に、オブジェクトの作成とその関係にも関係します。そのようなアプリケーションは、(制御フローではなく)オブジェクト作成の所有権をinvertし、オブジェクトの作成、オブジェクトのライフサイクル、およびオブジェクトの依存関係の注入を担当するコンテナが必要でした。これにより、アプリケーションオブジェクトが他の具体的なオブジェクトを作成することを排除します。
その意味では、DIはIoCと同じではありません。制御フローに関するものではありませんが、一種のIo *、すなわちオブジェクト作成の所有権の反転。
この質問に関しては、私はそのウィキがすでに詳細でわかりやすい説明を提供したと思います。ここで最も重要なものを引用します。
オブジェクト指向プログラミングでは、制御の反転を実装するための基本的な手法がいくつかあります。これらは:
- サービスロケーターパターンの使用依存性注入の使用(例:コンストラクター注入)パラメーター注入セッター注入インターフェース注入。
- コンテキスト化された検索を使用する
- テンプレートメソッドデザインパターンを使用する。
- 戦略デザインパターンの使用
依存性注入 について
依存性注入は、あるオブジェクト(または静的メソッド)が別のオブジェクトの依存関係を提供する技法です。依存関係は、使用できるオブジェクト(サービス)です。注入は、それを使用する依存オブジェクト(クライアント)に依存関係を渡すことです。
SOLIDのDから始めて、Scott Millettの著書 "Professional ASP.NET Design Patterns"のDIとIoCを見てみましょう。
依存性反転原理(DIP)
_ dip _ は、具体的な実装からクラスを分離し、それらを抽象クラスまたはインタフェースに依存させるためのものです。これは、実装ではなくインターフェースへのコーディングの原則を促進します。これにより、ユーザーが1つの実装に密接に結び付いていないことが保証され、システム内の柔軟性が高まります。
依存性注入(DI)と制御の反転(IoC)
DIPと密接に関連しているのは、DIの原則とIoCの原則です。 _ di _ は、コンストラクタ、メソッド、またはプロパティを介して低レベルクラスまたは依存クラスを提供する動作です。 DIと組み合わせて使用すると、これらの従属クラスをインターフェイスまたは抽象クラスに変換して、疎結合のシステムとなり、テストが容易になり、変更が容易になります。
IoC では、手続き型プログラミングと比較して、システムの制御の流れが逆になります。この例は IoCコンテナ です。その目的は、クライアントコードに具体的な実装を指定させずにサービスをクライアントコードにインジェクトすることです。この例では逆になっている制御は、サービスを受けるクライアントの動作です。
ミレー、C(2010)。プロのASP.NETデザインパターン。ワイリー出版。 7−8。
1)DIはChild-> objがparent-objに依存している動詞の依存は重要です。 2)IOCはChild-> objがプラットフォームのもとで実行されます。プラットフォームは、学校、大学、ダンスクラスなどです。ここで実行することは、どのプラットフォームプロバイダの下でも異なる意味を持つアクティビティです。
実例: `
//DI
child.getSchool();
//IOC
child.perform()// is a stub implemented by dance-school
child.flourish()// is a stub implemented by dance-school/school/
`
-AB
Dzone.com で最良の例を見つけました。これはIOCとDIの本当の違いを理解するのに本当に役立ちます
「IoCは、他の人が自分のためにオブジェクトを作成するときです。」したがって、コードに「new」キーワード(たとえば、MyCode c = new MyCode())を書く代わりに、オブジェクトは他の人によって作成されます。この「他人」は通常、IoCコンテナと呼ばれます。これは、オブジェクトのインスタンスを取得するためにrrsponsibility(control)をコンテナに渡すことをInversion of Controlと呼びます。つまり、new演算子を使用してオブジェクトを作成するのではなく、コンテナにそれを実行させます。
DI(Dependency Injection): Way of injecting properties to an object is
called
Dependency injection.
We have three types of Dependency injection
1) Constructor Injection
2) Setter/Getter Injection
3) Interface Injection
Spring will support only Constructor Injection and Setter/Getter Injection.
記事全文を読むIOC and 記事全文を読むDI