Auf Klassenebene ist es einfach.
"Abhängigkeitsinjektion" beantwortet einfach die Frage "Wie finde ich meine Mitarbeiter?" Mit "Sie werden an Sie herangeführt - Sie müssen sie nicht selbst holen". (Es ist ähnlich wie - aber nicht dasselbe wie - "Inversion of Control", wo die Frage "Wie ordne ich meine Operationen über meine Eingaben an?" Eine ähnliche Antwort hat.)
Der einzige Vorteil, den Ihre Mitarbeiter haben, besteht darin, dass der Client-Code Ihre Klasse verwenden kann, um ein Objektdiagramm zu erstellen, das seinen aktuellen Anforderungen entspricht. Sie haben die Form und die Wandlungsfähigkeit des Diagramms nicht willkürlich durch eine private Entscheidung festgelegt die konkreten Arten und den Lebenszyklus Ihrer Mitarbeiter.
(Alle anderen Vorteile der Testbarkeit, der losen Kopplung usw. ergeben sich größtenteils aus der Verwendung von Schnittstellen und weniger aus der Abhängigkeitsinjektion, obwohl DI natürlich die Verwendung von Schnittstellen fördert).
Es ist erwähnenswert, dass, wenn Sie vermeiden Sie Ihre eigenen Mitarbeiter instanziiert wird , Ihre Klasse muss daher seine Mitarbeiter von einem Konstruktor, eine Eigenschaft erhalten, oder ein Verfahren Argument (diese letztere Option wird oft übersehen, übrigens ... es tut Es ist nicht immer sinnvoll, dass die Kollaborateure einer Klasse Teil ihres "Staates" sind.
Und das ist auch gut so.
Auf der Anwendungsebene ...
Soviel zur klassenbezogenen Sicht der Dinge. Angenommen, Sie haben eine Reihe von Klassen, die der Regel "Ihre eigenen Mitarbeiter nicht instanziieren" folgen, und möchten aus ihnen einen Antrag stellen. Am einfachsten ist es, guten alten Code (ein wirklich nützliches Tool zum Aufrufen von Konstruktoren, Eigenschaften und Methoden!) Zu verwenden, um das gewünschte Objektdiagramm zu erstellen und Eingaben zu tätigen. (Ja, einige dieser Objekte in Ihrem Diagramm werden selbst Objektfabriken sein, die als Kollaborateure an andere langlebige Objekte im Diagramm weitergegeben wurden, die für den Service bereit sind ... Sie können nicht jedes Objekt vorkonstruieren! ).
... Sie müssen den Objektgraphen Ihrer App "flexibel" konfigurieren ...
Abhängig von Ihren anderen (nicht codebezogenen) Zielen möchten Sie dem Endbenutzer möglicherweise eine gewisse Kontrolle über das so bereitgestellte Objektdiagramm geben. Dies führt Sie in die eine oder andere Richtung eines Konfigurationsschemas, sei es eine Textdatei Ihres eigenen Designs mit einigen Name / Wert-Paaren, eine XML-Datei, eine benutzerdefinierte DSL, eine deklarative Graph-Beschreibungssprache wie YAML, eine zwingende Skriptsprache wie JavaScript oder etwas anderes, das für die jeweilige Aufgabe geeignet ist. Was auch immer erforderlich ist, um ein gültiges Objektdiagramm so zu erstellen, dass es den Anforderungen Ihrer Benutzer entspricht.
... kann eine bedeutende Designkraft sein.
Unter den extremsten Umständen dieses Typs können Sie sich für einen sehr allgemeinen Ansatz entscheiden und den Endbenutzern einen allgemeinen Mechanismus zum "Verkabeln" des von ihnen gewählten Objektgraphen an die Hand geben und ihnen sogar die Möglichkeit geben, konkrete Realisierungen von Schnittstellen zu erstellen Laufzeit! (Ihre Dokumentation ist ein glänzendes Juwel, Ihre Benutzer sind sehr schlau, kennen zumindest den groben Umriss des Objektgraphen Ihrer Anwendung, haben aber zufällig keinen Compiler zur Hand). Dieses Szenario kann theoretisch in einigen Unternehmenssituationen auftreten.
In diesem Fall verfügen Sie wahrscheinlich über eine deklarative Sprache, mit der Ihre Benutzer jeden Typ, die Zusammensetzung eines Objektgraphen dieser Typen und eine Palette von Schnittstellen, die der mythische Endbenutzer mischen und zuordnen kann, ausdrücken können. Um die kognitive Belastung Ihrer Benutzer zu verringern, bevorzugen Sie einen "Configuration by Convention" -Ansatz, sodass sie nur das interessierende Objekt-Graph-Fragment eingeben und überschreiben müssen, anstatt mit dem Ganzen zu ringen.
Du armer Arsch!
Da Sie nicht alles selbst aufschreiben wollten (aber im Ernst, sehen Sie sich eine YAML-Bindung für Ihre Sprache an), verwenden Sie eine Art DI-Framework.
Abhängig von der Reife dieses Frameworks haben Sie möglicherweise nicht die Möglichkeit, Konstruktor-Injection zu verwenden, auch wenn dies sinnvoll ist (die Mitarbeiter ändern sich nicht über die Lebensdauer eines Objekts), sodass Sie gezwungen sind, Setter Injection zu verwenden (auch wenn Kollaborateure ändern sich nicht über die Lebensdauer eines Objekts, und selbst wenn es keinen logischen Grund gibt, warum alle konkreten Implementierungen einer Schnittstelle Kollaborateure eines bestimmten Typs haben müssen . Wenn ja, befinden Sie sich derzeit in der Hölle der starken Kopplung, obwohl Sie in Ihrer gesamten Codebasis fleißig Schnittstellen verwendet haben - Horror!
Hoffentlich haben Sie ein DI-Framework verwendet, mit dem Sie Konstruktorinjektionen durchführen können, und Ihre Benutzer sind nur ein bisschen mürrisch , weil sie nicht mehr Zeit damit verbringen, über die spezifischen Dinge nachzudenken, die sie zum Konfigurieren benötigen, und ihnen eine für die Aufgabe besser geeignete Benutzeroberfläche zu geben zur Hand. (Um fair zu sein, haben Sie wahrscheinlich versucht, einen Weg zu finden, aber JavaEE hat Sie im Stich gelassen und Sie mussten auf diesen schrecklichen Hack zurückgreifen).
Bootnote
Zu keinem Zeitpunkt verwenden Sie Google Guice, wodurch der Codierer die Aufgabe, einen Objektgraphen mit Code zu erstellen, überflüssig macht ... indem er Code schreibt. Argh!