Unterschied zwischen Dependency Injection (DI) und Inversion of Control (IOC)

117

Ich habe viele Referenzen zu Dependency Injection (DI) und Inversion Of Control (IOC) gesehen, aber ich weiß nicht wirklich, ob es einen Unterschied zwischen ihnen gibt oder nicht.

Ich würde gerne einen oder beide verwenden, aber ich bin ein wenig verwirrt darüber, wie sie sich unterscheiden.

Mücke
quelle
Inversion of Control bezieht sich normalerweise auf die "Container", während sich Dependency Injection auf das tatsächliche Muster bezieht. Aber sie gehen Hand in Hand. Ich würde empfehlen, Martin Fowlers Artikel zu lesen , um das Thema in den Griff zu bekommen.
Ben Hoffstein
Abhängigkeitsinjektion ist ein Vorgang, der zu einer Befehlsstruktur mit dem Namen Inversion of Control führt. Sie sind von Natur aus miteinander verbunden.
2
DI ist eine Form von IoC, ich habe in dieser Antwort
2
Ich würde sagen, DI ist ein Sonderfall des IOC. Traditionelle Steuerung geht Modul-> Modul vom Modulmanager anfordern, in DI wird es zum Modulmanager invertiert-> angeforderte Abhängigkeiten vom Modul abrufen.
Rafał Dowgird
Mit anderen Worten, IoC ist im Grunde eine Implementierung der Verwendung von DI. Verstehe ich das richtig?
dance2die

Antworten:

53

Definitionen

Die Inversion der Steuerung ist ein Entwurfsparadigma mit dem Ziel, das Bewusstsein für konkrete Implementierungen aus dem Anwendungsframeworkcode zu verringern und den domänenspezifischen Komponenten Ihrer Anwendung mehr Kontrolle zu verleihen. In einem herkömmlichen von oben nach unten entworfenen System fließt der logische Fluss des Anwendungs- und Abhängigkeitsbewusstseins von den obersten Komponenten, die zuerst entworfen wurden, zu denjenigen, die zuletzt entworfen wurden. Insofern ist die Umkehrung der Steuerung eine fast wörtliche Umkehrung des Steuerungs- und Abhängigkeitsbewusstseins in einer Anwendung.

Die Abhängigkeitsinjektion ist ein Muster, das zum Erstellen von Instanzen von Klassen verwendet wird, auf die andere Klassen angewiesen sind, ohne beim Kompilieren zu wissen, welche Implementierung verwendet wird, um diese Funktionalität bereitzustellen.

Zusammen arbeiten

Inversion der Steuerung kann Abhängigkeitsinjektion verwenden, da ein Mechanismus erforderlich ist, um die Komponenten zu erstellen, die die spezifische Funktionalität bereitstellen. Andere Optionen sind vorhanden und werden verwendet, z. B. Aktivatoren, Factory-Methoden usw.. Frameworks müssen jedoch nicht auf diese Utility-Klassen verweisen, wenn Framework-Klassen stattdessen die benötigten Abhängigkeiten akzeptieren können.

Beispiele

Ein Beispiel für diese Konzepte ist das Plug-In-Framework in Reflector . Die Plug-Ins haben eine große Kontrolle über das System, obwohl die Anwendung zum Zeitpunkt der Kompilierung nichts über die Plug-Ins wusste. Für jedes dieser Plug-Ins wird eine einzelne Methode aufgerufen: Initialize if memory serve, die die Steuerung an das Plug-In übergibt. Das Framework weiß nicht, was sie tun werden, sondern lässt sie es einfach tun. Die Steuerung wurde von der Hauptanwendung übernommen und der Komponente übertragen, die die spezifische Arbeit ausführt. Umkehrung der Kontrolle.

Das Anwendungsframework ermöglicht den Zugriff auf seine Funktionalität über eine Vielzahl von Dienstanbietern. Ein Plug-In erhält beim Erstellen Verweise auf die Dienstanbieter. Diese Abhängigkeiten ermöglichen es dem Plug-in, eigene Menüelemente hinzuzufügen, die Anzeige von Dateien zu ändern, eigene Informationen in den entsprechenden Bedienfeldern anzuzeigen usw. Da die Abhängigkeiten von der Schnittstelle übergeben werden, können sich die Implementierungen ändern, und die Änderungen werden die nicht beschädigen Code, solange der Vertrag intakt bleibt.

Zu der Zeit wurde eine Factory-Methode verwendet, um die Plug-Ins unter Verwendung von Konfigurationsinformationen, Reflektion und des Activator-Objekts (mindestens in .NET) zu erstellen. Heutzutage gibt es Tools, MEF zum einen, die eine größere Auswahl an Optionen beim Einfügen von Abhängigkeiten ermöglichen, einschließlich der Fähigkeit eines Anwendungsframeworks, eine Liste von Plugins als Abhängigkeit zu akzeptieren.

Zusammenfassung

Obwohl diese Konzepte unabhängig voneinander verwendet werden können und Vorteile bieten, ermöglichen sie zusammen das Schreiben von flexiblerem, wiederverwendbarem und testbarem Code. Als solche sind sie wichtige Konzepte für die Gestaltung objektorientierter Lösungen.

Futter
quelle
3
Nein, IoC ist ein älteres Konzept und unabhängig von DI (unabhängig von IoC). Nehmen Sie zum Beispiel das Struts-Framework (Java): Es basiert stark auf IoC, verwendet jedoch kein DI.
Rogério
1
@ Rogério - Du machst einen guten Punkt, dass die beiden Konzepte einander nicht erfordern. Ich habe meine Antwort aktualisiert, um dies zu verdeutlichen, und dann kurz beschrieben, wie einige Frameworks sie zusammen verwenden, um Code zu ermöglichen, der lockerer gekoppelt ist.
Chuck
Die einfachste Anwendung von IoC wäre wahrscheinlich ActionListener. Anstatt den Code prozedural zu verarbeiten, wird der Code für die Ereignisbehandlung an benutzerdefinierten Code delegiert. Hiermit invertieren Sie die Steuerung.
Mike
0

Guter Artikel zum Verständnis von IOC und DI http://martinfowler.com/articles/injection.html

IOC (Inversion of Control)

IOC bedeutet

  1. Kodierung an Schnittstelle (eine Komponente sollte von der Schnittstelle der anderen Komponente und nicht von impl abhängen) und z

    interface iComp_2 {...}
    
    class Comp_1 {
        iComp_2 c2 = ….;
    }
    
  2. Entfernen des für die Komponentenimplementierung spezifischen Codes, z

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

IOC kann auf eine der folgenden Arten erreicht werden:

1. DI (Dependency Injection)

3 types of DI

1.1 Constructor Injection

1.2 Setter Injection

1.3 Interface Injection

2. Service Locator

DI-Container (Dependency Injection)

Laufzeit-Impl-Bestimmung und keine Kompilierungszeit: Bestimmt zur Laufzeit, welche konkrete Implementierung einer Schnittstelle basierend auf einer Konfigurationsdatei verwendet werden soll (daher wissen wir zur Kompilierungszeit nicht, welches Impl verwendet werden soll, und erhöhen so die Konfigurierbarkeit der Anwendung). . Es ist eine Implementierung, bei der die konkrete Beziehung zwischen verschiedenen Modulen zur Laufzeit festgelegt wird.

Instanziierung von impl nach dem Einfügen von Abhängigkeiten: Nach dem Bestimmen des impl instanziiert es diesen impl, indem es zuerst alle seine Abhängigkeiten erstellt (in der Konfigurationsdatei angegeben) und diese Abhängigkeiten dann in diesen impl einfügt

Instanz-Lebenszyklusverwaltung: DI-Container enthalten normalerweise nur Verweise auf Objekte, die für die Verwaltung der Lebenszyklen benötigt werden oder die für zukünftige Injektionen wiederverwendet werden, z. B. Singletons oder Fliehgewichte. Wenn der Container so konfiguriert ist, dass für jeden Aufruf des Containers neue Instanzen einiger Komponenten erstellt werden, vergisst er normalerweise nur das erstellte Objekt. Andernfalls würde es dem Müllsammler schwer fallen, alle diese Objekte zu sammeln, wenn er sie nicht mehr verwendet.

Yatendra Goel
quelle
6
Hast du den Artikel "Injection" wirklich gelesen? IOC bedeutet nicht , was diese Antwort sagt, überhaupt nicht.
Rogério
-3

Ich würde sagen, "Inversion of Control" ist eine Möglichkeit, ein System zu entwerfen, bei dem alle Module als abstrakte Einheiten gedacht sind.

"Abhängigkeitsinjektion" ist eine Implementierung, bei der die konkrete Beziehung zwischen verschiedenen Modulen zur "Laufzeit" festgelegt wird.

mB.
quelle
-4

Die Umkehrung der Kontrolle ist ein allgemeines Konzept, in funktionalen Sprachen erfolgt dies normalerweise unter Verwendung von Fortsetzungen. Hiermit können Sie eine API schreiben, bei der beide Seiten "Anrufer" und keine "Angerufenen" sind. In anderen, statischeren Umgebungen verfügen Sie nicht über diese Funktionalität. Daher benötigen Sie diesen Hack, um Hinweise in den Kontrollfluss einzufügen.

Javier
quelle