Inversion der Kontrolle gegen Abhängigkeitsinjektion


525

Nach dem von Martin Fowler verfassten Artikel ist die Umkehrung der Steuerung das Prinzip, bei dem der Steuerungsfluss eines Programms invertiert wird: Anstelle des Programmierers, der den Ablauf eines Programms steuert, übernehmen die externen Quellen (Framework, Dienste, andere Komponenten) die Kontrolle es. Es ist, als würden wir etwas an etwas anderes anschließen. Er erwähnte ein Beispiel zu EJB 2.0:

Beispielsweise definiert die Session Bean-Schnittstelle ejbRemove, ejbPassivate (im Sekundärspeicher gespeichert) und ejbActivate (aus dem passiven Zustand wiederhergestellt). Sie können nicht steuern, wann diese Methoden aufgerufen werden, sondern nur, was sie tun. Der Container ruft uns an, wir nennen es nicht.

Dies führt zu dem Unterschied zwischen Framework und Bibliothek:

Die Inversion der Kontrolle ist ein wesentlicher Bestandteil dessen, was ein Framework von einer Bibliothek unterscheidet. Eine Bibliothek besteht im Wesentlichen aus einer Reihe von Funktionen, die Sie aufrufen können. Diese sind heutzutage normalerweise in Klassen unterteilt. Jeder Aufruf erledigt einige Arbeiten und gibt die Kontrolle an den Client zurück.

Ich denke, der Standpunkt, dass DI IOC ist, bedeutet, dass die Abhängigkeit eines Objekts invertiert ist: Anstatt seine eigenen Abhängigkeiten, seinen Lebenszyklus zu steuern, erledigt es etwas anderes für Sie. Aber, wie Sie mir von Hand über DI erzählt haben, ist DI nicht unbedingt IOC. Wir können immer noch DI und kein IOC haben.

In diesem Artikel (aus der Pococapsule, einem anderen IOC-Framework für C / C ++) wird jedoch vorgeschlagen, dass die IOC-Container und DI-Frameworks aufgrund von IOC und DI J2EE weit überlegen sind, da J2EE den Framework-Code in die Komponenten mischt Dadurch wird es nicht zu einem einfachen alten Java / C ++ - Objekt (POJO / POCO).

Inversion anderer Kontrollcontainer als des Abhängigkeitsinjektionsmusters (Archivlink)

Zusätzliche Lektüre, um zu verstehen, was das Problem mit dem alten komponentenbasierten Entwicklungsframework ist, das zum zweiten Artikel oben führt: Warum und was von Inversion of Control (Archivlink)

Meine Frage : Was genau ist IOC und DI? Ich bin verwirrt. Basierend auf Pococapsule ist IOC etwas Wichtigeres als nur die Umkehrung der Steuerung zwischen Objekten oder Programmierern und Frameworks.


2
Hier ist eine gute Zusammenfassung zu diesem Thema: IoC gegen DI (Dependency Inject) gegen SL (Service Locator): tinyurl.com/kk4be58 - Auszug aus der URL: IoC gegen DI (Dependency Injection)? IoC ist das allgemeine Konzept, bei dem die Steuerung des Flusses vom Client-Code zum Framework invertiert wird , wodurch „etwas für den Client getan wird“. SL (Service Locator) und DI (Dependency Injection) sind zwei Entwurfsmuster, die sich aus IoC ergeben.
Swab.Jat

Um meine zwei Cent hinzuzufügen, wenn man daran interessiert ist, wie die Abhängigkeitsinjektion in einem Coffee-Shop-Thema hilfreich sein kann, habe ich hier einen Artikel dazu geschrieben: digigene.com/design-patterns/dependency-injection-coffeeshop
Ali Nem


Abhängigkeitsinversion: Abhängig von Abstraktionen, nicht von Konkretionen. Umkehrung der Kontrolle: Main vs Abstraction und wie der Main der Klebstoff der Systeme ist. Dies sind einige gute Beiträge, die darüber sprechen: coderstower.com/2019/03/26/… coderstower.com/2019/04/02/… coderstower.com/2019/04/09/…
Daniel Andres Pelaez Lopez

Lesen Sie über diese Tiefe, es wird alle martinfowler.com/articles/…
Dushman

Antworten:


644

IoC ist ein allgemeiner Begriff, der bedeutet, dass die Anwendung die Methoden nicht in einem Framework aufruft, sondern dass das Framework Implementierungen aufruft, die von der Anwendung bereitgestellt werden.

DI ist eine Form von IoC, bei der Implementierungen über Konstruktoren / Setter / Service-Lookups an ein Objekt übergeben werden, von denen das Objekt abhängig ist, um sich korrekt zu verhalten.

IoC ohne DI wäre beispielsweise das Vorlagenmuster, da die Implementierung nur durch Unterklassifizierung geändert werden kann.

DI-Frameworks verwenden DI und können Schnittstellen (oder Anmerkungen in Java) definieren, um die Übergabe der Implementierungen zu vereinfachen.

IoC-Container sind DI-Frameworks, die außerhalb der Programmiersprache arbeiten können. In einigen Fällen können Sie konfigurieren, welche Implementierungen in weniger invasiven Metadatendateien (z. B. XML) verwendet werden sollen. Mit einigen können Sie IoC ausführen, was normalerweise unmöglich wäre, wie das Einfügen einer Implementierung bei Pointcuts .

Siehe auch diesen Artikel von Martin Fowler .


2
Danke für die Antwort. Das andere Papier legt jedoch nahe, dass IOC-Container mit IOC EJB weit überlegen sind, während Martin Fowler vorschlägt, dass EJB ein typisches Beispiel für IOC ist.
Amumu

5
Das EJB-Management ist wirklich ein typisches Beispiel für IoC. Sie können dies daran erkennen, dass der Lebenszyklus eines EJB vom Container und nicht vom Programmierer verwaltet wird. Der Programmierer erstellt oder zerstört keine EJB-Instanz, da das Steuerelement an den Server delegiert ist . Das ist das Konzept von IoC: Der externe Code steuert, wann Ihr Code aufgerufen wird. Dies ist normalerweise das Gegenteil von dem, was er die meiste Zeit getan hat.
Brandizzi

2
IoC ist ein allgemeiner Begriff, der bedeutet, dass die Anwendung die Methoden nicht in einem Framework aufruft, sondern dass das Framework Implementierungen aufruft, die von der Anwendung bereitgestellt werden. Können Sie uns mehr darüber erklären?
Imad Alazani

21
Aka Hollywood-Prinzip : Rufen Sie uns nicht an, wir rufen Sie an. Überlässt den Aufruf dem Framework und nicht der Anwendung.
Garrett Hall

@ImadAlazani, lesen Sie besser den Artikel, den Garrett beigefügt hat. Dieser enthält eine ausführliche Diskussion zum Invertieren des Steuerelements vom Anwendungscode zum Framework.
MengT

210

Kurz gesagt, IoC ist ein viel weiter gefasster Begriff, der DI umfasst, aber nicht darauf beschränkt ist

Der Begriff Inversion of Control (IoC) bezeichnete ursprünglich jede Art von Programmierstil, bei dem ein Gesamtrahmen oder eine Laufzeit den Programmfluss kontrollierte

Bevor DI einen Namen hatte, begannen die Leute, Frameworks, die Abhängigkeiten verwalten, als Inversion von Kontrollcontainern zu bezeichnen, und bald driftete die Bedeutung von IoC allmählich in Richtung dieser bestimmten Bedeutung: Inversion der Kontrolle über Abhängigkeiten.

Inversion of Control (IoC) bedeutet, dass Objekte keine anderen Objekte erstellen, auf die sie sich verlassen, um ihre Arbeit zu erledigen. Stattdessen erhalten sie die benötigten Objekte von einer externen Quelle (z. B. einer XML-Konfigurationsdatei).

Dependency Injection (DI) bedeutet, dass dies ohne Objektintervention erfolgt, normalerweise durch eine Framework-Komponente, die Konstruktorparameter übergibt und Eigenschaften festlegt.


1
IoC scheint nur ein weiterer Begriff für das Prinzip der Frequenzinversion zu sein, oder?
Todd Vance

@ToddVance - Ja, ich denke, IoC und DIP sind dasselbe. DIP und DI sind nicht dasselbe. IoC kann ohne DI durchgeführt werden, DI kann jedoch nicht ohne IoC durchgeführt werden.
Eljay

2
@ToddVance - Nein, DIP und IoC sind keine Synonyme und nicht verwandt.
TSmith

3
Ha, deshalb bin ich hier in diesem Thread ... "Inversion of Control vs Dependency Injection"
Todd Vance

50

Geben Sie hier die Bildbeschreibung ein
Quelle

IoC ( I nversion o f C teuerung): - Es ist ein allgemeiner Begriff und auf verschiedene Weise implementiert (Veranstaltungen, Teilnehmer usw.).

DI ( D ependency I njection): - DI ist ein Untertyp von IoC und wird durch Konstruktorinjektion, Setterinjektion oder Schnittstelleninjektion implementiert .

Spring unterstützt jedoch nur die folgenden zwei Typen:

  • Setter-Injektion
    • Setter-basierte DI wird realisiert, indem Setter-Methoden für die Beans des Benutzers aufgerufen werden, nachdem ein Konstruktor ohne Argumente oder eine statische Factory-Methode ohne Argumente aufgerufen wurde, um deren Bean zu instanziieren.
  • Konstruktorinjektion
    • Konstruktorbasiertes DI wird durch Aufrufen eines Konstruktors mit einer Reihe von Argumenten realisiert, die jeweils einen Kollaborateur darstellen. Auf diese Weise können wir überprüfen, ob die injizierten Beans nicht null sind und schnell fehlschlagen (Fehler bei der Kompilierung und nicht zur Laufzeit) Beim Starten der Anwendung selbst erhalten wir NullPointerException: bean does not exist. Die Konstruktorinjektion ist eine bewährte Methode zum Injizieren von Abhängigkeiten.

1
Es ist nicht korrekt zu sagen, dass Spring die Eigenschaftsinjektion nicht unterstützt. Es tut. Und es ist eine schlechte Praxis, da stimme ich zu.
Kekko12

Spring @Autowired Annotation ist meiner Meinung nach eine Möglichkeit zur Eigenschaftsinjektion
Sajith

49

DI ist eine Teilmenge von IoC

  • IoC bedeutet, dass Objekte keine anderen Objekte erstellen, auf die sie sich verlassen, um ihre Arbeit zu erledigen. Stattdessen erhalten sie die benötigten Objekte von einem externen Dienst (z. B. XML-Datei oder einzelner App-Dienst). 2 Implementierungen von IoC, die ich benutze, sind DI und ServiceLocator.
  • DI bedeutet, dass das IoC-Prinzip, abhängige Objekte zu erhalten, ohne Verwendung konkreter Objekte, aber Abstraktionen (Schnittstellen) durchgeführt wird. Dies macht die Kette aller Komponenten testbar, da Komponenten höherer Ebenen nicht von Komponenten niedrigerer Ebenen abhängen, sondern nur von der Schnittstelle. Mocks implementieren diese Schnittstellen.

Hier sind einige andere Techniken, um IoC zu erreichen .


Ich würde nicht sagen, dass IoC bedeutet, keine Objekte zu erstellen. Wenn Sie nicht die Klassenmethode direkt aufrufen, sondern die Schnittstellenmethode - dies ist eine Umkehrung der Steuerung (da in diesem Fall der Aufrufer nicht vom Aufruf des Codes abhängt) und hängt überhaupt nicht mit der Objekterstellung zusammen. Ein weiteres Beispiel für IoC sind Veranstaltungen und Delegierte
Eugene Gorbovoy

19

Da sich alle Antworten auf die Theorie konzentrieren, möchte ich anhand eines ersten Beispielansatzes demonstrieren:

Angenommen, wir erstellen eine Anwendung, die eine Funktion zum Senden von SMS-Bestätigungsnachrichten enthält, sobald die Bestellung versandt wurde. Wir werden zwei Klassen haben, eine ist für das Senden der SMS (SMSService) und eine andere für die Erfassung von Benutzereingaben (UIHandler) verantwortlich. Unser Code sieht wie folgt aus:

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!");
    }
}

Die obige Implementierung ist nicht falsch, aber es gibt nur wenige Probleme:
-) Angenommen, Sie möchten in einer Entwicklungsumgebung an eine Textdatei gesendete SMS speichern, anstatt ein SMS-Gateway zu verwenden, um dies zu erreichen. Wir werden am Ende die konkrete Implementierung von (SMSService) durch eine andere Implementierung ändern. Wir verlieren an Flexibilität und müssen in diesem Fall den Code neu schreiben.
-) Wir werden am Ende die Verantwortlichkeiten der Klassen mischen, unser (UIHandler) sollte niemals etwas über die konkrete Implementierung von (SMSService) wissen, dies sollte außerhalb der Klassen unter Verwendung von "Schnittstellen" erfolgen. Wenn dies implementiert ist, können wir das Verhalten des Systems ändern, indem wir den (SMSService), der verwendet wird, gegen einen anderen Scheindienst austauschen, der dieselbe Schnittstelle implementiert. Dieser Dienst speichert SMS in einer Textdatei, anstatt sie an mobileNumber zu senden.

Um die oben genannten Probleme zu beheben, verwenden wir Schnittstellen, die von unserem (SMSService) und dem neuen (MockSMSService) implementiert werden. Grundsätzlich zeigt das neue Interface (ISMSService) dasselbe Verhalten beider Dienste wie der folgende Code:

public interface ISMSService
{
    void SendSMS(string phoneNumber, string body);
}

Dann werden wir unsere (SMSService) -Implementierung ändern, um die (ISMSService) -Schnittstelle zu implementieren:

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);
    }
}

Jetzt können wir einen neuen Mock-up-Service (MockSMSService) mit völlig unterschiedlicher Implementierung über dieselbe Schnittstelle erstellen:

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);
    }
}

An dieser Stelle können wir den Code in (UIHandler) ändern, um die konkrete Implementierung des Dienstes (MockSMSService) wie folgt zu verwenden:

public class UIHandler
{
    public void SendConfirmationMsg(string mobileNumber)
    {
        ISMSService _SMSService = new MockSMSService();
        _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!");
    }
}

Wir haben viel Flexibilität erreicht und die Trennung von Bedenken in unseren Code implementiert, aber wir müssen noch eine Änderung an der Codebasis vornehmen, um zwischen den beiden SMS-Diensten zu wechseln. Wir müssen also Dependency Injection implementieren .

Um dies zu erreichen, müssen wir eine Änderung an unserem (UIHandler) -Klassenkonstruktor implementieren, um die Abhängigkeit durchzuleiten. Auf diese Weise kann der Code, der den (UIHandler) verwendet, bestimmen, welche konkrete Implementierung von (ISMSService) verwendet werden soll:

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!");
    }
}

Jetzt ist das UI-Formular, das mit der Klasse (UIHandler) kommuniziert, dafür verantwortlich, zu übergeben, welche Implementierung der Schnittstelle (ISMSService) verwendet werden soll. Dies bedeutet, dass wir das Steuerelement invertiert haben. Der (UIHandler) ist nicht mehr dafür verantwortlich, zu entscheiden, welche Implementierung verwendet werden soll, der aufrufende Code. Wir haben das Inversion of Control- Prinzip implementiert, bei dem DI eine Art davon ist.

Der UI-Formularcode lautet wie folgt:

class Program
{
    static void Main(string[] args)
    {
        ISMSService _SMSService = new MockSMSService(); // dependency

        UIHandler _UIHandler = new UIHandler(_SMSService);
        _UIHandler.SendConfirmationMsg("96279544480");

        Console.ReadLine();
    }
}

Tolle Erklärung
ZiviMagic

19

IOC (Inversion of Control) : Wenn Sie dem Container die Kontrolle geben, um eine Instanz des Objekts abzurufen, wird dies als Inversion of Control bezeichnet. Wenn Sie also kein Objekt mit dem neuen Operator erstellen, lassen Sie den Container dies für Sie tun.

DI (Dependency Injection) : Die Methode zum Injizieren von Eigenschaften in ein Objekt wird als Dependency Injection bezeichnet .

Wir haben drei Arten der Abhängigkeitsinjektion :

  1. Konstruktorinjektion
  2. Setter / Getter-Injektion
  3. Schnittstelleninjektion

Die Feder unterstützt nur die Konstruktorinjektion und die Setter / Getter-Injektion .


5

Aber die Federdokumentation sagt, dass sie gleich sind.

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-introduction

In der ersten Zeile " IoC wird auch als Abhängigkeitsinjektion (DI) bezeichnet ".


1
Ich denke, was sie ansprechen wollten, ist, dass DI eine sehr weit verbreitete Variante des IoC-Entwurfsmusters ist, die fast leicht als IoC oder DI bezeichnet werden kann - es sei denn, die Dokumentation enthält explizite Verweise, die etwas anderes vorschlagen.
ha9u63ar

5
"IoC ist auch als Dependency Injection (DI) bekannt" ... Pferdefedern!
MikeM

5

IoC - Inversion of Control ist ein allgemeiner Begriff, unabhängig von der Sprache. Es werden eigentlich nicht die Objekte erstellt, sondern es wird beschrieben, auf welche Weise ein Objekt erstellt wird.

DI - Abhängigkeitsinjektion ist ein konkreter Begriff, bei dem wir Abhängigkeiten des Objekts zur Laufzeit mithilfe verschiedener Injektionstechniken bereitstellen, d. H. Setter Injection, Constructor Injection oder Interface Injection.


4

Die Umkehrung der Steuerung ist ein Entwurfsparadigma mit dem Ziel, den Zielkomponenten Ihrer Anwendung, die die Arbeit erledigen, mehr Kontrolle zu geben.
Die Abhängigkeitsinjektion ist ein Muster, mit dem Instanzen von Objekten erstellt werden, auf die sich andere Objekte stützen, ohne zur Kompilierungszeit zu wissen, welche Klasse zur Bereitstellung dieser Funktionalität verwendet wird.

Es gibt verschiedene grundlegende Techniken, um die Umkehrung der Steuerung zu implementieren. Diese sind:

  • Verwenden eines Fabrikmusters
  • Verwenden eines Service Locator-Musters
  • Verwenden einer Abhängigkeitsinjektion eines der folgenden Typen:

    1). Eine Konstruktorinjektion
    2). Eine Setterinjektion
    3). Eine Schnittstelleninjektion

4

DI und IOC sind zwei Entwurfsmuster, die sich hauptsächlich darauf konzentrieren, eine lose Kopplung zwischen Komponenten bereitzustellen , oder einfach eine Art und Weise, wie wir die herkömmlichen Abhängigkeitsbeziehungen zwischen Objekten entkoppeln, damit die Objekte nicht eng miteinander verbunden sind.

Mit den folgenden Beispielen versuche ich, beide Konzepte zu erklären.

Zuvor haben wir Code wie diesen geschrieben

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();
}

Bei der Abhängigkeitsinjektion kümmert sich der Abhängigkeitsinjektor um die Instanziierung von Objekten

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();
}

Der obige Prozess, die Steuerung einem anderen (zum Beispiel dem Container) für die Instanziierung und Injektion zu geben, kann als Inversion of Control bezeichnet werden, und der Prozess, bei dem der IOC-Container die Abhängigkeit für uns injiziert, kann als Abhängigkeitsinjektion bezeichnet werden.

IOC ist das Prinzip, bei dem der Steuerungsfluss eines Programms invertiert wird: Anstatt dass der Programmierer den Ablauf eines Programms steuert, steuert das Programm den Ablauf, indem es den Overhead für den Programmierer verringert. Der Prozess, den das Programm zum Einfügen der Abhängigkeit verwendet, wird als bezeichnet DI

Die beiden Konzepte arbeiten zusammen und bieten uns die Möglichkeit, viel flexibleren, wiederverwendbaren und gekapselten Code zu schreiben, was sie zu wichtigen Konzepten beim Entwerfen objektorientierter Lösungen macht.

Auch zum Lesen empfehlen.

Was ist Abhängigkeitsinjektion?

Sie können auch eine meiner ähnlichen Antworten hier überprüfen

Unterschied zwischen Inversion der Kontrolle und Abhängigkeitsinjektion


3

Inversion of Control ist ein generisches Entwurfsprinzip der Softwarearchitektur, mit dessen Hilfe wiederverwendbare, modulare Software-Frameworks erstellt werden können, die einfach zu warten sind.

Es ist ein Entwurfsprinzip, bei dem der Kontrollfluss von der generisch geschriebenen Bibliothek oder dem wiederverwendbaren Code "empfangen" wird.

Um es besser zu verstehen, sehen wir uns an, wie wir in früheren Codierungstagen codiert haben. In prozeduralen / traditionellen Sprachen steuert die Geschäftslogik im Allgemeinen den Fluss der Anwendung und "ruft" den generischen oder wiederverwendbaren Code / die Funktionen auf. In einer einfachen Konsolenanwendung wird mein Steuerungsfluss beispielsweise durch die Anweisungen meines Programms gesteuert, die möglicherweise die Aufrufe einiger allgemein wiederverwendbarer Funktionen umfassen.

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

Im Gegensatz dazu sind bei IoC die Frameworks der wiederverwendbare Code, der die Geschäftslogik "aufruft".

In einem Windows-basierten System ist beispielsweise bereits ein Framework zum Erstellen von UI-Elementen wie Schaltflächen, Menüs, Fenstern und Dialogfeldern verfügbar. Wenn ich die Geschäftslogik meiner Anwendung schreibe, werden die Ereignisse des Frameworks meinen Geschäftslogikcode aufrufen (wenn ein Ereignis ausgelöst wird) und NICHT das Gegenteil.

Obwohl der Code des Frameworks meine Geschäftslogik nicht kennt, kann er meinen Code trotzdem aufrufen. Dies wird durch Ereignisse / Delegaten, Rückrufe usw. erreicht. Hier ist die Steuerung des Flusses "invertiert".

Anstatt den Kontrollfluss von statisch gebundenen Objekten abhängig zu machen, hängt der Fluss vom Gesamtobjektgraphen und den Beziehungen zwischen verschiedenen Objekten ab.

Die Abhängigkeitsinjektion ist ein Entwurfsmuster, das das IoC-Prinzip zum Auflösen von Abhängigkeiten von Objekten implementiert.

In einfacheren Worten, wenn Sie versuchen, Code zu schreiben, erstellen und verwenden Sie verschiedene Klassen. Eine Klasse (Klasse A) kann andere Klassen (Klasse B und / oder D) verwenden. Klasse B und D sind also Abhängigkeiten der Klasse A.

Eine einfache Analogie wird ein Klassenauto sein. Ein Auto kann von anderen Klassen wie Motor, Reifen und mehr abhängen.

Die Abhängigkeitsinjektion schlägt vor, dass anstelle der abhängigen Klassen (hier Class Car), die ihre Abhängigkeiten erstellen (Class Engine und Klasse Tire), der Klasse die konkrete Instanz der Abhängigkeit injiziert werden sollte.

Lassen Sie uns mit einem praktischeren Beispiel verstehen. Bedenken Sie, dass Sie Ihren eigenen TextEditor schreiben. Unter anderem können Sie eine Rechtschreibprüfung durchführen, mit der der Benutzer die Tippfehler in seinem Text überprüfen kann. Eine einfache Implementierung eines solchen Codes kann sein:

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;

    }

}

Auf den ersten Blick sieht alles rosig aus. Der Benutzer wird Text schreiben. Der Entwickler erfasst den Text, ruft die CheckSpellings-Funktion auf und findet eine Liste der Tippfehler, die er dem Benutzer anzeigt.

Alles scheint gut zu funktionieren, bis eines schönen Tages ein Benutzer anfängt, Französisch im Editor zu schreiben.

Um mehr Sprachen unterstützen zu können, benötigen wir mehr SpellChecker. Wahrscheinlich Französisch, Deutsch, Spanisch usw.

Hier haben wir einen eng gekoppelten Code erstellt, wobei "English" SpellChecker eng mit unserer TextEditor-Klasse gekoppelt ist. Dies bedeutet, dass unsere TextEditor-Klasse vom EnglishSpellChecker abhängig ist oder mit anderen Worten, EnglishSpellCheker ist die Abhängigkeit für TextEditor. Wir müssen diese Abhängigkeit entfernen. Darüber hinaus benötigt unser Texteditor eine Möglichkeit, die konkrete Referenz einer Rechtschreibprüfung nach Ermessen des Entwicklers zur Laufzeit zu speichern.

Wie wir in der Einführung von DI gesehen haben, schlägt es vor, dass die Klasse mit ihren Abhängigkeiten injiziert werden sollte. Es sollte also in der Verantwortung des aufrufenden Codes liegen, alle Abhängigkeiten in die aufgerufene Klasse / den aufgerufenen Code einzufügen. So können wir unseren Code als umstrukturieren

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.

    }

}

In unserem Beispiel sollte die TextEditor-Klasse die konkrete Instanz des ISpellChecker-Typs erhalten.

Jetzt kann die Abhängigkeit in Constructor, eine öffentliche Eigenschaft oder eine Methode eingefügt werden.

Versuchen wir, unsere Klasse mit Constructor DI zu ändern. Die geänderte TextEditor-Klasse sieht ungefähr so ​​aus:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

Damit der aufrufende Code beim Erstellen des Texteditors den entsprechenden SpellChecker-Typ in die Instanz des TextEditors einfügen kann.

Den vollständigen Artikel können Sie hier lesen


3

IOC (Inversion of Control): Die Übergabe der Kontrolle an den Container zum Abrufen der Objektinstanz wird als Inversion of Control bezeichnet. Anstatt dass Sie ein Objekt mit einem neuen Operator erstellen , lassen Sie den Container dies für Sie tun.

DI (Dependency Injection): Die Übergabe der erforderlichen Parameter (Eigenschaften) von XML an ein Objekt (in POJO CLASS) wird als Dependency Injection bezeichnet.


2

IOC gibt an, dass externe Klassen die Klassen einer Anwendung verwalten, und externe Klassen bedeuten, dass ein Container die Abhängigkeit zwischen Anwendungsklassen verwaltet. Das Grundkonzept von IOC besteht darin, dass Programmierer Ihre Objekte nicht erstellen müssen, sondern beschreiben müssen, wie sie erstellt werden sollen.

Die Hauptaufgaben des IoC-Containers sind: Instanziieren der Anwendungsklasse. um das Objekt zu konfigurieren. um die Abhängigkeiten zwischen den Objekten zusammenzusetzen.

DI ist der Prozess zum Bereitstellen der Abhängigkeiten eines Objekts zur Laufzeit mithilfe der Setter-Injektion oder der Konstruktor-Injektion.


2

IOC (Inversion of Control) ist im Grunde ein Entwurfsmusterkonzept, bei dem Abhängigkeiten entfernt und entkoppelt werden, um den Fluss nichtlinear zu machen, und der Container / oder eine andere Entität die Bereitstellung von Abhängigkeiten verwalten kann. Es folgt tatsächlich Hollywoods Prinzip "Rufen Sie uns nicht an, wir rufen Sie an". Also die Unterschiede zusammenfassen.

Umkehrung der Kontrolle: - Es ist ein Oberbegriff, um die Abhängigkeiten zu entkoppeln und ihre Bereitstellung zu delegieren. Dies kann auf verschiedene Arten implementiert werden (Ereignisse, Delegaten usw.).

Abhängigkeitsinjektion: - DI ist ein Subtyp des IOC und wird durch Konstruktorinjektion, Setterinjektion oder Methodeninjektion implementiert.

Der folgende Artikel beschreibt dies sehr anschaulich.

https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO


1

Ich denke, die Idee kann klar demonstriert werden, ohne in objektorientierte Unkräuter zu geraten, die die Idee durcheinander zu bringen scheinen.

// dependency injection
function doSomething(dependency) {
    // do something with your dependency
}

// in contrast to creating your dependencies yourself
function doSomething() {
    dependency = getDependencySomehow()
}

// inversion of control
application = makeApp(authenticate, handleRequest, sendResponse)
application.run(getRequest())

// in contrast to direct control or a "library" style
application = makeApp()
request = application.getRequest()

if (application.authenticate(request.creds)) {
    response = application.handleRequest(request)
    application.sendResponse(response)
}

Wenn Sie den Kopf neigen und die Augen zusammenknicken, werden Sie feststellen, dass DI eine bestimmte Implementierung von IoC mit besonderen Bedenken ist. Anstatt Modelle und Verhaltensweisen in ein Anwendungsframework oder eine Operation höherer Ordnung einzufügen, fügen Sie Variablen in eine Funktion oder ein Objekt ein.


0

Beginnen wir mit D von SOLID und schauen uns DI und IoC aus Scott Milletts Buch "Professional ASP.NET Design Patterns" an:

Prinzip der Abhängigkeitsinversion (DIP)

Beim DIP geht es darum, Ihre Klassen von konkreten Implementierungen zu isolieren und sie von abstrakten Klassen oder Schnittstellen abhängig zu machen. Es fördert das Mantra der Codierung auf einer Schnittstelle und nicht auf einer Implementierung, wodurch die Flexibilität innerhalb eines Systems erhöht wird, indem sichergestellt wird, dass Sie nicht eng an eine Implementierung gekoppelt sind.

Abhängigkeitsinjektion (DI) und Inversion der Kontrolle (IoC)

Eng mit dem DIP verbunden sind das DI-Prinzip und das IoC-Prinzip. DI ist der Vorgang des Bereitstellens einer niedrigen oder abhängigen Klasse über einen Konstruktor, eine Methode oder eine Eigenschaft. In Verbindung mit DI können diese abhängigen Klassen in Schnittstellen oder abstrakte Klassen invertiert werden, was zu lose gekoppelten Systemen führt, die in hohem Maße testbar und leicht zu ändern sind.

In IoC ist der Steuerungsfluss eines Systems im Vergleich zur prozeduralen Programmierung umgekehrt. Ein Beispiel hierfür ist ein IoC-Container , dessen Zweck darin besteht, Dienste in den Clientcode einzufügen, ohne dass der Clientcode die konkrete Implementierung angibt. Die Steuerung in diesem Fall, die invertiert wird, ist die Handlung des Clients, der den Dienst erhält.

Millett, C (2010). Professionelle ASP.NET-Entwurfsmuster. Wiley Publishing. 7-8.


0

// ICO, DI, vor 10 Jahren, so waren sie:

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 ();
    }
}

Jetzt mit Spring 3,4 oder spätestens wie unten

public class  AuditDAOImpl implements Audit{

    //dependency

     //Now control is shifted to Spring. Container find the object and provide it. 
    @Autowired
    AuditDAO auditDAO = null;

}

Insgesamt wird die Steuerung vom alten Konzept des gekoppelten Codes zu den Frameworks wie Spring umgekehrt, die das Objekt verfügbar machen. Soweit ich weiß, ist dies also IOC und Abhängigkeitsinjektion, wie Sie wissen, wenn wir das abhängige Objekt mit einem Konstruktor oder Setter in ein anderes Objekt injizieren. Injizieren bedeutet im Grunde, es als Argument zu übergeben. Im Frühjahr haben wir eine XML- und Annotations-basierte Konfiguration, in der wir das Bean-Objekt definieren und das abhängige Objekt mit dem Konstruktor- oder Setter-Injektionsstil übergeben.


0

Ich habe auf Dzone.com das beste Beispiel gefunden, das wirklich hilfreich ist, um den wirklichen Unterschied zwischen IOC und DI zu verstehen

"IoC ist, wenn jemand anderes Objekte für Sie erstellt." Anstatt also "neues" Schlüsselwort (z. B. MyCode c = new MyCode ()) in Ihren Code zu schreiben, wird das Objekt von einer anderen Person erstellt. Diese "andere Person" wird normalerweise als IoC-Container bezeichnet. Dies bedeutet, dass wir die Verantwortung (Kontrolle) an den Container übergeben, um die Instanz des Objekts zu erhalten. Dies wird als Inversion der Kontrolle bezeichnet. Anstatt dass Sie ein Objekt mit einem neuen Operator erstellen, lassen Sie den Container dies für Sie tun.

   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.

Lesen Sie den vollständigen Artikel IOC und den vollständigen Artikel DI


0

1) DI ist Child-> obj hängt von parent-obj ab. Das Verb hängt davon ab, ist wichtig. 2) IOC ist Child-> obj unter einer Plattform durchführen. wo Plattform Schule, Hochschule, Tanzklasse sein könnte. Hier ist perform eine Aktivität mit unterschiedlichen Auswirkungen unter jedem Plattformanbieter.

praktisches Beispiel: `

//DI
child.getSchool();
//IOC
child.perform()// is a stub implemented by dance-school
child.flourish()// is a stub implemented by dance-school/school/

`

-AB


0

Zu dieser Frage würde ich sagen, dass das Wiki bereits detaillierte und leicht verständliche Erklärungen geliefert hat. Ich werde hier nur das Wichtigste zitieren.

Implementierung von IoC

Bei der objektorientierten Programmierung gibt es mehrere grundlegende Techniken, um die Umkehrung der Steuerung zu implementieren. Diese sind:

  1. Verwenden eines Service-Locator-Musters Verwenden der Abhängigkeitsinjektion, z. B. Konstruktorinjektion Parameterinjektion Setterinjektion Schnittstelleninjektion;
  2. Verwenden einer kontextualisierten Suche;
  3. Verwenden des Entwurfsmusters für die Vorlagenmethode;
  4. Verwenden des Strategieentwurfsmusters

Wie für die Abhängigkeitsinjektion

Die Abhängigkeitsinjektion ist eine Technik, bei der ein Objekt (oder eine statische Methode) die Abhängigkeiten eines anderen Objekts liefert. Eine Abhängigkeit ist ein Objekt, das verwendet werden kann (ein Dienst). Eine Injektion ist die Übergabe einer Abhängigkeit an ein abhängiges Objekt (einen Client), das sie verwenden würde.


0

Das IoC-Konzept wurde ursprünglich in der Ära der prozeduralen Programmierung gehört. Aus historischer Sicht sprach IoC daher über die Umkehrung des Eigentums an Kontrollfluss , dh wer die Verantwortung besitzt, die Funktionen in der gewünschten Reihenfolge aufzurufen - ob es sich um die Funktionen selbst handelt oder ob Sie sie in eine externe Entität umkehren sollten.

Als jedoch die OOP auftauchte, wurde im OOP-Kontext über IoC gesprochen, wobei Anwendungen neben dem Kontrollfluss auch die Objekterstellung und ihre Beziehungen betreffen. Solche Anwendungen wollte umkehren , das Eigentum an Objekterstellungs (statt Kontrollfluss) und benötigt einen Behälter, der für die Objekterstellung, Objektlebenszyklus und Injizieren Abhängigkeiten der Anwendung verantwortlich ist , Objekte dadurch eliminiert Anwendungsobjekte von der Erstellung anderen konkreten Objekt.

In diesem Sinne ist DI nicht dasselbe wie Io C , da es nicht um Kontrollfluss geht, sondern um eine Art Io * , dh Umkehrung des Eigentums an der Objekterstellung.

Was ist falsch daran, DI und IoC zu erklären?


0

IoC alias Inversion of Control bezieht sich auf die Steuerung des Erstellens von Instanzen, die vom Spring-Container ausgeführt werden. Das Steuerelement zum Erstellen und Erstellen von Objekten wird vom Container übernommen. Der Container erstellt die Objekte und fügt sie in unsere Anwendung ein.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.