Ich entwerfe ein neues System und möchte wissen, was Inversion of Control (IOC) ist und was noch wichtiger ist, wann es verwendet werden soll.
Muss es mit Interfaces implementiert werden oder kann es mit Klassen durchgeführt werden?
Ich entwerfe ein neues System und möchte wissen, was Inversion of Control (IOC) ist und was noch wichtiger ist, wann es verwendet werden soll.
Muss es mit Interfaces implementiert werden oder kann es mit Klassen durchgeführt werden?
Antworten:
IoC (siehe Inversion of Control in Wikipedia) ist in Fällen anwendbar, in denen eine Komponente eine Aufgabe nicht vollständig ausführen kann, weil sie nicht über die erforderlichen Informationen oder Funktionen verfügt.
Das einfachste Beispiel für ein IoC- Muster wären Callback-Funktionen in C. Sie können beispielsweise die Funktion deklarieren:
void Iterator(void *list, Func* f)
Was über das list
Anwenden der f
Funktion auf jedes Element iteriert . Die Iterator
Funktion weiß nicht, wie die einzelnen Elemente verarbeitet werden. Sie geben lediglich eine Funktion als Argument an und verarbeiten sie.
Wie das vorherige Beispiel zeigt, können Sie mit IoC Ihr Programm in separate Komponenten entkoppeln, die nichts voneinander wissen. Eine der häufigsten Versionen von IoC ist Dependecy Injection .
In Dependency Injection muss jede Komponente eine Liste von Abhängigkeiten deklarieren, die zur Ausführung ihrer Aufgabe erforderlich sind. Zur Laufzeit führt eine spezielle Komponente, die als IoC-Container bezeichnet wird, eine Bindung zwischen diesen Komponenten durch. Es wird versucht, Werte für veröffentlichte Komponentenabhängigkeiten bereitzustellen.
Hier ist ein Beispiel in Pseudocode:
class Foo
{
<Require Boo>Constructor(Boo boo){ boo.DoSomething }
}
In diesem Beispiel Foo
verfügt die Klasse über einen Konstruktor, für den ein Argument vom Typ erforderlich ist Boo
, um eine Aktion auszuführen.
Sie können eine Instanz einer Klasse Foo
mit folgendem Code erstellen :
MyContainer.Create(typeof Foo)
MyContainer
- ist ein IoC-Container , der dafür sorgt, dass die Instanz abgerufenBoo
und an den Foo
Konstruktor übergeben wird.
Zusammenfassend lässt sich sagen, dass Sie mit IoC Ihr Programm in separate Teile aufteilen können. Das ist gut, weil:
In einigen Fällen jedoch, IoC kann machen Code schwerer zu verstehen.
Wenn Sie ein gutes Beispiel für die Verwendung von IoC in der Praxis sehen möchten, schauen Sie sich Mircosoft Composite UI Application Block und CompositeWPF an
Ich hoffe meine Erklärung hilft dir.
Grüße,
aku
Da ich mich vor kurzem selbst damit befasst und alle Lesezeichen aufbewahrt habe, war das Folgende für mich von unschätzbarem Wert, um etwas über IOC / DI zu lernen.
Martin Fowlers Originalartikel über IOC / DI
Einige Konzepte, die Sie zuerst kennen sollten
Eine hervorragende Sammlung von IOC / DI-Tutorials
Buch über IOC / DI von Manning Press
Quelle und Erklärung, wie Sie Ihr eigenes IOC erstellen - Denn das Lesen von Quellcode ist immer der beste Weg, um ein Konzept zu verstehen.
Hey JMS, im Grunde genommen können Sie mit IoC / DI definieren, welche Implementierung Sie einmal verwenden, und eine statische Kopie Ihres Containers aufbewahren, damit Sie jedes Mal darauf verweisen können, wenn Sie darauf verweisen möchten.
Die Wikipedia wird Ihnen wahrscheinlich helfen, aber ich wollte auf Ihren zweiten Teil verweisen - ja, Abhängigkeitsinjektion kann für Klassen durchgeführt werden (dh jedes Mal, wenn dieser Klassentyp an eine Methode übergeben werden muss, verwenden Sie diese Klasse), aber es ist besser zu Verwenden Sie Schnittstellen, da Sie auf diese Weise ändern können, welche Version eines Providers, Repositorys usw. Sie verwenden, indem Sie es in Ihrem Setup erneut referenzieren.
Angenommen, Sie hatten eine Schnittstelle zum Einlesen eines Streams und eine XMLStreamReader- und eine SQLStreamReader-Implementierung. Anschließend können Sie den Verweis auf die Schnittstelle an Ihre Methoden übergeben und in Ihrem IoC-Container angeben, welche verwendet werden soll.
Sie können also festlegen, dass öffentliche List ReadPeople (IStreamReader-Reader) und in Ihrem Setup für Ihren IoC-Container jedes Mal, wenn Sie einen IStreamReader erwarten, SQLStreamReader verwenden.
Wenn Sie es sich später anders überlegen, müssen Sie es nur an einer Stelle ändern (dem Setup Ihres Containers), und es spielt keine Rolle, wie viele Methoden nach einem IStreamReader fragen, er erhält immer die Standardeinstellung, die Sie Ihrem Container anvertraut haben auftischen.
Angenommen, Sie haben einen Validator, mit dem Sie überprüfen können, ob ein Unternehmen in Ihrem System gültig ist. Ihr "BusinessValidator" verfügt möglicherweise über ein Feld vom Typ AddressValidator, das den Adressteil des Geschäfts validiert. Wenn Sie den BusinessValidator testen möchten, ohne externen Code (dh den addressValidator-Code) auszuführen, können Sie, wenn Sie eine Art von IoC / DI in Ihrem Framework verwendet haben, einfach einen nachgebildeten addressValidator an seiner Stelle "injizieren" und müssen sich nicht um das Testen kümmern Code außerhalb des Bereichs der zu testenden Klasse.