Die meisten der für die Verwendung von Dependency Injection angeführten Beispiele können wir auch anhand des Factory-Musters lösen. Es sieht so aus, als ob der Unterschied zwischen Abhängigkeitsinjektion und Werkseinstellung bei Verwendung / Design unscharf oder dünn ist.
Einmal hat mir jemand gesagt, dass es einen Unterschied macht, wie Sie es verwenden!
Ich habe einmal StructureMap, einen DI-Container, verwendet, um ein Problem zu lösen. Später habe ich ihn neu gestaltet, um mit einer einfachen Factory zu arbeiten, und Verweise auf StructureMap entfernt.
Kann mir jemand sagen, was der Unterschied zwischen ihnen ist und wo was zu verwenden ist, was hier die beste Vorgehensweise ist?
dependency-injection
factory-pattern
design-patterns
Binoj Antony
quelle
quelle
Antworten:
Wenn Sie eine Factory verwenden, ist Ihr Code weiterhin für die Erstellung von Objekten verantwortlich. Mit DI lagern Sie diese Verantwortung an eine andere Klasse oder ein Framework aus, das von Ihrem Code getrennt ist.
quelle
Manually-Injected Dependency
Ich würde vorschlagen, die Konzepte schlicht und einfach zu halten. Die Abhängigkeitsinjektion ist eher ein Architekturmuster für die lose Kopplung von Softwarekomponenten. Das Factory-Muster ist nur eine Möglichkeit, die Verantwortung für das Erstellen von Objekten anderer Klassen einer anderen Entität zu übertragen. Das Factory-Muster kann als Werkzeug zur Implementierung von DI aufgerufen werden. Die Abhängigkeitsinjektion kann auf viele Arten wie DI mithilfe von Konstruktoren, mithilfe von Mapping-XML-Dateien usw. implementiert werden.
quelle
Abhängigkeitsspritze
Anstatt die Teile selbst zu instanziieren, fragt ein Auto nach den Teilen, die es zum Funktionieren benötigt.
Fabrik
Fügt die Teile zu einem vollständigen Objekt zusammen und verbirgt den Betontyp vor dem Anrufer.
Ergebnis
Wie Sie sehen können, ergänzen sich Fabriken und DI.
Erinnerst du dich an Goldlöckchen und die drei Bären? Nun, Abhängigkeitsinjektion ist so ähnlich. Hier sind drei Möglichkeiten, um dasselbe zu tun.
Beispiel 1 - Dies ist das Schlimmste, da dadurch die Abhängigkeit vollständig ausgeblendet wird. Wenn Sie die Methode als Black Box betrachten würden, hätten Sie keine Ahnung, dass ein Auto erforderlich ist.
Beispiel 2 - Das ist etwas besser, weil wir jetzt wissen, dass wir ein Auto brauchen, da wir in einer Autofabrik vorbeikommen. Aber diesmal fahren wir zu viel vorbei, da die Methode eigentlich nur ein Auto benötigt. Wir fahren in einer Fabrik vorbei, um das Auto zu bauen, wenn das Auto außerhalb der Methode gebaut und übergeben werden könnte.
Beispiel 3 - Dies ist ideal, da die Methode genau das verlangt , was sie benötigt. Nicht zu viel oder zu wenig. Ich muss keine MockCarFactory schreiben, nur um MockCars zu erstellen, ich kann das Modell direkt übergeben. Es ist direkt und die Schnittstelle lügt nicht.
Dieser Google Tech Talk von Misko Hevery ist erstaunlich und die Grundlage für das, woraus ich mein Beispiel abgeleitet habe. http://www.youtube.com/watch?v=XcT4yYu_TTs
quelle
Der Grund, warum Dependency Injection (DI) und Factory Patterns ähnlich sind, liegt darin, dass es sich um zwei Implementierungen von Inversion of Control (IoC) handelt, einer Softwarearchitektur. Einfach ausgedrückt handelt es sich um zwei Lösungen für dasselbe Problem.
Um die Frage zu beantworten, besteht der Hauptunterschied zwischen dem Factory-Muster und DI darin, wie die Objektreferenz erhalten wird. Bei der Abhängigkeitsinjektion, wie der Name schon sagt, wird die Referenz in Ihren Code injiziert oder gegeben. Bei Factory-Mustern muss Ihr Code die Referenz anfordern, damit Ihr Code das Objekt abruft. Beide Implementierungen entfernen oder entkoppeln die Verknüpfung zwischen dem Code und der zugrunde liegenden Klasse oder dem Typ der vom Code verwendeten Objektreferenz.
Es ist erwähnenswert, dass Factory-Muster (oder tatsächlich Abstract Factory-Muster, bei denen es sich um Fabriken handelt, die neue Fabriken zurückgeben, die Objektreferenzen zurückgeben) geschrieben werden können, um den zur Laufzeit angeforderten Objekttyp oder die angeforderte Objektklasse dynamisch auszuwählen oder mit diesem zu verknüpfen. Dies macht sie dem Service Locator-Muster, das eine weitere Implementierung des IoC darstellt, sehr ähnlich (noch mehr als DI).
Das Factory-Designmuster ist ziemlich alt (in Bezug auf Software) und gibt es schon eine Weile. Seit der jüngsten Popularität des Architekturmusters IoC erlebt es eine Wiederbelebung.
Ich denke, wenn es um IoC-Entwurfsmuster geht: Injektoren werden injiziert, Locators werden lokalisiert und die Fabriken wurden überarbeitet.
quelle
Es gibt Probleme, die mit der Abhängigkeitsinjektion leicht zu lösen sind und die mit einer Reihe von Fabriken nicht so einfach zu lösen sind.
Ein Unterschied zwischen einerseits der Inversion der Steuerung und der Abhängigkeitsinjektion (IOC / DI) und andererseits einem Service Locator oder einer Reihe von Fabriken (Fabrik) besteht in folgenden Punkten:
IOC / DI ist ein vollständiges Ökosystem von Domänenobjekten und -diensten an und für sich. Es richtet alles für Sie so ein, wie Sie es angeben. Ihre Domain - Objekte und Dienste werden von dem Behälter aufgebaut und konstruieren sich nicht: sie daher nicht über alle Abhängigkeiten auf den Behälter oder auf irgendwelchen Fabriken. IOC / DI ermöglicht ein extrem hohes Maß an Konfigurierbarkeit, wobei die gesamte Konfiguration an einem einzigen Ort (Aufbau des Containers) auf der obersten Ebene Ihrer Anwendung (der GUI, dem Web-Frontend) erfolgt.
Factory abstrahiert einen Teil der Konstruktion Ihrer Domain-Objekte und -Dienste. Domänenobjekte und -dienste sind jedoch weiterhin dafür verantwortlich, herauszufinden, wie sie sich selbst konstruieren und wie sie alle Dinge erhalten, von denen sie abhängen. Alle diese "aktiven" Abhängigkeiten filtern sich durch alle Ebenen Ihrer Anwendung. Es gibt keinen einzigen Ort, an dem Sie alles konfigurieren können.
quelle
Ein Nachteil von DI ist, dass es keine Objekte mit Logik initialisieren kann. Wenn ich beispielsweise ein Zeichen mit zufälligem Namen und Alter erstellen muss, ist DI nicht die Wahl gegenüber dem Fabrikmuster. Mit Fabriken können wir den Zufallsalgorithmus aus der Objekterstellung einfach kapseln, der eines der Entwurfsmuster unterstützt, das als "Verkapseln, was variiert" bezeichnet wird.
quelle
Von: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html
quelle
Ich glaube, DI ist eine Art Abstraktionsschicht in Fabriken, aber sie bieten auch Vorteile, die über die Abstraktion hinausgehen. Eine echte Fabrik weiß, wie man einen einzelnen Typ instanziiert und konfiguriert. Eine gute DI-Schicht bietet die Möglichkeit, durch Konfiguration viele Typen zu instanziieren und zu konfigurieren.
Für ein Projekt mit einigen einfachen Typen, dessen Konstruktion eine relativ stabile Geschäftslogik erfordert, ist das Fabrikmuster offensichtlich einfach zu verstehen, zu implementieren und funktioniert gut.
OTOH: Wenn Sie ein Projekt mit zahlreichen Typen haben, deren Implementierungen sich voraussichtlich häufig ändern, bietet Ihnen DI durch die Konfiguration die Flexibilität, dies zur Laufzeit zu tun, ohne Ihre Fabriken neu kompilieren zu müssen.
quelle
Theorie
Es sind zwei wichtige Punkte zu beachten:
Wer schafft Objekte
Welche Art von Objekten verwaltet es:
Praktisches Beispiel für die Verwendung von Factory- und Abhängigkeitsinjektion in einem einzelnen Projekt
Anwendungsmodul zum Erstellen einer Bestellung, die mehrere Einträge enthält, die als Bestellposition bezeichnet werden.
Nehmen wir an, wir möchten folgende Ebenenarchitektur erstellen:
Domänenobjekte können Objekte sein, die in der Datenbank gespeichert sind. Repository (DAO) hilft beim Abrufen von Objekten aus der Datenbank. Der Dienst stellt API für andere Module bereit. Ermöglicht Operationen am
order
ModulEntitäten, die sich in der Datenbank befinden, sind Order und OrderLine. Bestellung kann mehrere Bestellpositionen haben.
Jetzt kommt wichtiger Designteil. Sollten Module außerhalb dieses Bereichs OrderLines selbst erstellen und verwalten? Nein. Die Bestellposition sollte nur vorhanden sein, wenn Sie eine Bestellung zugeordnet haben. Es ist am besten, wenn Sie die interne Implementierung für externe Klassen verbergen können.
Aber wie kann man eine Bestellung ohne Kenntnisse über OrderLines erstellen?
Fabrik
Jemand, der eine neue Bestellung erstellen möchte, hat OrderFactory verwendet (wodurch Details darüber verborgen werden, wie wir eine Bestellung erstellen).
So wird es in IDE aussehen. Klassen außerhalb des
domain
Pakets werdenOrderFactory
anstelle des Konstruktors innerhalb verwendetOrder
OrderRepository und OrderService werden vom Abhängigkeitsinjektionsframework verwaltet. Das Repository ist für die Verwaltung der CRUD-Operationen in der Datenbank verantwortlich. Der Dienst injiziert das Repository und verwendet es, um die richtigen Domänenklassen zu speichern / zu finden.
quelle
[Factory]: Usually responsible for creation of stateful objects [Dependency Injections] More likely to create stateless objects
Ich verstehe nicht warumIch weiß, dass diese Frage alt ist, aber ich möchte meine fünf Cent hinzufügen,
Ich denke, dass die Abhängigkeitsinjektion (DI) in vielerlei Hinsicht einem konfigurierbaren Factory Pattern (FP) ähnelt, und in diesem Sinne können Sie alles, was Sie mit DI tun können, mit einer solchen Factory tun.
Wenn Sie beispielsweise spring verwenden, haben Sie die Möglichkeit, Ressourcen automatisch zu verdrahten (DI) oder Folgendes zu tun:
Und dann verwenden Sie diese 'mb'-Instanz, um etwas zu tun. Ist das nicht ein Anruf bei einer Fabrik, die Ihnen eine Instanz zurückgibt?
Der einzige wirkliche Unterschied, den ich zwischen den meisten FP-Beispielen bemerke, besteht darin, dass Sie konfigurieren können, was "myBean" in einer XML-Datei oder einer anderen Klasse ist, und dass ein Framework als Factory funktioniert, aber ansonsten ist es dasselbe und Sie kann sicherlich eine Factory haben, die eine Konfigurationsdatei liest oder die Implementierung nach Bedarf erhält.
Und wenn Sie mich nach meiner Meinung fragen (und ich weiß, dass Sie es nicht getan haben), glaube ich, dass DI dasselbe tut, aber die Entwicklung nur komplexer macht, warum?
Zum einen müssen Sie zur Konfiguration selbst gehen, um zu wissen, welche Implementierung für jede Bean verwendet wird, die Sie automatisch mit DI verdrahten.
aber ... was ist mit dem Versprechen, dass Sie die Implementierung des von Ihnen verwendeten Objekts nicht kennen müssen? pfft! Ernsthaft? Wenn Sie einen solchen Ansatz verwenden ... sind Sie nicht derselbe, der die Implementierung schreibt? und selbst wenn Sie dies nicht tun, sehen Sie sich nicht fast die ganze Zeit an, wie die Implementierung das tut, was sie tun soll?
und zum einen spielt es keine Rolle, wie sehr Ihnen ein DI-Framework verspricht , dass Sie davon entkoppelte Dinge ohne Abhängigkeiten zu ihren Klassen erstellen. Wenn Sie ein Framework verwenden, erstellen Sie alles, was dazu gehört, wenn Sie müssen Ändern Sie den Ansatz oder den Rahmen, es wird keine leichte Aufgabe sein ... NIE! ... aber da Sie alles um dieses spezielle Framework herum aufbauen, anstatt sich Gedanken darüber zu machen, was die beste Lösung für Ihr Unternehmen ist, werden Sie dabei mit einem großen Problem konfrontiert sein.
Tatsächlich ist die einzige echte Geschäftsanwendung für einen FP- oder DI-Ansatz, die ich sehen kann, wenn Sie die zur Laufzeit verwendeten Implementierungen ändern müssen , aber zumindest die mir bekannten Frameworks erlauben Ihnen dies nicht. Sie müssen gehen Alles perfekt in der Konfiguration zur Entwicklungszeit und wenn Sie das brauchen, verwenden Sie einen anderen Ansatz.
Wenn ich also eine Klasse habe, die in zwei Bereichen in derselben Anwendung unterschiedliche Leistungen erbringt (z. B. zwei Unternehmen einer Holding), muss ich das Framework so konfigurieren, dass zwei verschiedene Beans erstellt werden, und meinen Code anpassen, um jeden zu verwenden. Ist das nicht dasselbe, als würde ich einfach so etwas schreiben:
das gleiche wie das:
Und das:
In jedem Fall müssen Sie etwas in Ihrer Anwendung ändern, egal ob Klassen oder Konfigurationsdateien, aber Sie müssen es tun und erneut bereitstellen.
Wäre es nicht schön, so etwas zu tun:
Und auf diese Weise legen Sie den Code der Fabrik fest, um zur Laufzeit die richtige Implementierung zu erhalten, abhängig vom Unternehmen des protokollierten Benutzers? Nun, das wäre hilfreich. Sie können einfach ein neues JAR mit den neuen Klassen hinzufügen und die Regeln möglicherweise auch zur Laufzeit festlegen (oder eine neue Konfigurationsdatei hinzufügen, wenn Sie diese Option offen lassen), ohne Änderungen an vorhandenen Klassen vorzunehmen. Dies wäre eine dynamische Fabrik!
Wäre das nicht hilfreicher, als zwei Konfigurationen für jedes Unternehmen schreiben zu müssen und vielleicht sogar zwei verschiedene Anwendungen für jedes Unternehmen zu haben?
Sie können mir sagen, dass ich den Wechsel zur Laufzeit nie durchführen muss, also konfiguriere ich die App. Wenn ich die Klasse erbe oder eine andere Implementierung verwende, ändere ich einfach die Konfiguration und stelle sie erneut bereit. Ok, das kann man auch mit einer Fabrik machen. Und sei ehrlich, wie oft machst du das? Vielleicht nur, wenn Sie eine App haben, die irgendwo anders in Ihrem Unternehmen verwendet wird, und Sie den Code an ein anderes Team weitergeben, und diese werden solche Dinge tun. Aber hey, das kann man auch mit der Fabrik machen und wäre mit einer dynamischen Fabrik noch besser !!
Wie auch immer, der Kommentarbereich ist offen für dich, um mich zu töten.
quelle
IOC ist ein Konzept, das auf zwei Arten umgesetzt wird. Abhängigkeitserstellung und Abhängigkeitsinjektion, Factory / Abstract Factory sind Beispiele für die Erstellung von Abhängigkeiten. Die Abhängigkeitsinjektion ist Konstruktor, Setter und Schnittstelle. Der Kern von IOC besteht darin, nicht von den konkreten Klassen abhängig zu sein, sondern die Zusammenfassung von Methoden (z. B. eine Schnittstelle / abstrakte Klasse) zu definieren und diese Zusammenfassung zu verwenden, um die Methode der konkreten Klasse aufzurufen. Geben Sie wie das Factory-Muster die Basisklasse oder Schnittstelle zurück. In ähnlicher Weise verwenden die Abhängigkeitsinjektion die Basisklasse / Schnittstelle, um den Wert für Objekte festzulegen.
quelle
Mit der Abhängigkeitsinjektion muss der Client seine Abhängigkeiten nicht selbst abrufen, sondern alles wird zuvor vorbereitet.
Bei Fabriken muss jemand diese anrufen, um die generierten Objekte an den Ort zu bringen, an dem sie benötigt werden.
Der Unterschied liegt hauptsächlich in dieser einen Zeile, in der die Fabrik aufgerufen und das konstruierte Objekt abgerufen wird.
Aber in Fabriken müssen Sie diese 1 Zeile überall dort schreiben, wo Sie ein solches Objekt benötigen. Mit DI müssen Sie die Verkabelung (Beziehung zwischen Nutzung und erstelltem Objekt) nur einmal erstellen und sich danach überall auf die Anwesenheit des Objekts verlassen. Auf der anderen Seite erfordert DI oft etwas mehr Arbeit (wie viel vom Framework abhängt) auf der Vorbereitungsseite.
quelle
Ich hatte die gleiche Frage, sobald ich über DI gelesen hatte und landete in diesem Beitrag. Schließlich habe ich das verstanden, aber bitte korrigieren Sie mich, wenn ich falsch liege.
"Vor langer Zeit gab es kleine Königreiche mit eigenen Leitungsgremien, die Entscheidungen auf der Grundlage ihrer eigenen schriftlichen Regeln kontrollierten und trafen. Später bildete sich eine große Regierung, die all diese kleinen Leitungsgremien beseitigte, die ein Regelwerk (Verfassung) haben und durch Gerichte umgesetzt werden."
Die Leitungsgremien der kleinen Königreiche sind "Fabriken".
Die große Regierung ist der "Dependency Injector".
quelle
Sie können sich diesen Link ansehen , um einen Vergleich der beiden (und anderer) Ansätze in einem realen Beispiel zu erhalten.
Wenn sich die Anforderungen ändern, ändern Sie grundsätzlich mehr Code, wenn Sie Fabriken anstelle von DI verwenden.
Dies gilt auch für manuelles DI (dh wenn es kein externes Framework gibt, das die Abhängigkeiten zu Ihren Objekten bereitstellt, Sie sie jedoch in jedem Konstruktor übergeben).
quelle
Die meisten Antworten hier erklären konzeptionelle Unterschiede und Implementierungsdetails von beiden. Ich konnte jedoch keine Erklärung für den Unterschied in der Anwendung finden, welche IMO die wichtigste ist und nach der das OP gefragt hat. Lassen Sie mich dieses Thema erneut eröffnen ...
Genau. In 90% der Fälle können Sie die Objektreferenz entweder mit Factory oder DI erhalten, und normalerweise erhalten Sie letztere. In weiteren 10% der Fälle ist die Verwendung von Factory nur der richtige Weg . Diese Fälle umfassen das Abrufen von Objekten durch Variablen zu Laufzeitparametern. So was:
In diesem Fall
client
ist es nicht möglich , von DI zu kommen (oder erfordert zumindest eine hässliche Problemumgehung). Als allgemeine Regel für die Entscheidung: Wenn eine Abhängigkeit ohne berechnete Laufzeitparameter erhalten werden kann, wird DI bevorzugt, andernfalls verwenden Sie Factory.quelle
Ich glaube, dass DI eine Möglichkeit ist, eine Bohne zu konfigurieren oder zu instanziieren. Der DI kann auf viele Arten wie Konstruktor, Setter-Getter usw. durchgeführt werden.
Das Fabrikmuster ist nur eine andere Möglichkeit, Bohnen zu instanziieren. Dieses Muster wird hauptsächlich verwendet, wenn Sie Objekte mit dem Factory-Design-Muster erstellen müssen, da Sie bei Verwendung dieses Musters die Eigenschaften einer Bean nicht konfigurieren, sondern nur das Objekt instanziieren.
Überprüfen Sie diesen Link: Abhängigkeitsinjektion
quelle
Binoj,
Ich glaube nicht, dass Sie einen über den anderen wählen müssen.
Das Verschieben einer abhängigen Klasse oder Schnittstelle zu einem Klassenkonstruktor oder Setter folgt dem DI-Muster. Das Objekt, das Sie an den Konstruktor oder die Menge übergeben, kann mit Factory implementiert werden.
Wann verwenden? Verwenden Sie das Muster oder die Muster in Ihrem Entwickler-Steuerhaus. Womit fühlen sie sich am wohlsten und finden es am einfachsten zu verstehen.
quelle
Ich glaube, 3 wichtige Aspekte bestimmen Objekte und ihre Verwendung:
1. Instanziierung (einer Klasse zusammen mit etwaiger Initialisierung).
2. Injektion (der so erstellten Instanz), wo es erforderlich ist.
3. Lebenszyklusmanagement (der so erstellten Instanz).
Unter Verwendung des Factory-Musters wird der erste Aspekt (Instanziierung) erreicht, die verbleibenden zwei sind jedoch fraglich. Die Klasse, die andere Instanzen verwendet, muss die Fabriken fest codieren (anstatt Instanzen zu erstellen), was lose Kopplungsfähigkeiten behindert. Außerdem, LebenszyklusmanagementDie Anzahl der Instanzen wird zu einer Herausforderung in einer großen Anwendung, in der eine Factory an mehreren Stellen verwendet wird (insbesondere wenn die Factory den Lebenszyklus der zurückgegebenen Instanz nicht verwaltet, wird sie hässlich). viel besser als Fabriken.
Bei Verwendung eines DI (mit IoC-Muster) werden andererseits alle 3 außerhalb des Codes (zum DI-Container) abstrahiert, und die verwaltete Bean benötigt nichts über diese Komplexität. Lose Kupplung , ein sehr wichtiges architektonisches Ziel, kann leise und bequem erreicht werden. Ein weiteres wichtiges architektonisches Ziel ist die Trennung von Anliegen
Während die Fabriken für kleine Anwendungen geeignet sind, ist es für große besser, DI gegenüber Fabriken zu wählen.
quelle
Meine Gedanken:
Abhängigkeitsinjektion: Übergeben Sie Mitarbeiter als Parameter an die Konstruktoren. Dependency Injection Framework: Eine generische und konfigurierbare Factory zum Erstellen der Objekte, die als Parameter an die Konstruktoren übergeben werden sollen.
quelle
Ein Injection Framework ist eine Implementierung des Factory-Musters.
Es hängt alles von Ihren Anforderungen ab. Wenn Sie das Factory-Muster in einer Anwendung implementieren müssen, werden Ihre Anforderungen höchstwahrscheinlich von einer der unzähligen Implementierungen von Injection Frameworks erfüllt.
Sie sollten Ihre eigene Lösung nur dann einführen, wenn Ihre Anforderungen von keinem der Frameworks von Drittanbietern erfüllt werden können. Je mehr Code Sie schreiben, desto mehr Code müssen Sie pflegen. Code ist eine Verbindlichkeit, kein Vermögenswert.
Argumente darüber, welche Implementierung Sie verwenden sollten, sind nicht so grundlegend wie das Verständnis der architektonischen Anforderungen Ihrer Anwendung.
quelle
Factory Design Pattern
Das Werksmuster ist gekennzeichnet durch
Sie können einige Dinge beobachten, wenn Sie sich wie folgt fragen
Diese werden durch Abhängigkeitsinjektion behandelt.
Abhängigkeitsspritze
Sie können auf verschiedene Arten Abhängigkeiten injizieren. Der Einfachheit halber können Sie mit Interface Injection fortfahren
In DI erstellt der Container die erforderlichen Instanzen und "injiziert" sie in das Objekt.
Somit entfällt die statische Instanziierung.
Beispiel:
quelle
Von einem Nennwert aus sehen sie gleich aus
In sehr einfachen Worten hilft Factory Pattern, ein Erstellungsmuster, uns ein Objekt zu erstellen - "Definieren Sie eine Schnittstelle zum Erstellen eines Objekts". Wenn wir eine Art Objektpool mit Schlüsselwerten haben (z. B. Dictionary) und den Schlüssel an die Factory übergeben (ich beziehe mich auf das Simple Factory-Muster), können Sie den Typ auflösen. Job erledigt! Das Dependency Injection Framework (wie Structure Map, Ninject, Unity ... usw.) scheint dagegen dasselbe zu tun.
Aber ... "Das Rad nicht neu erfinden"
Aus architektonischer Sicht ist es eine Bindungsschicht und "Das Rad nicht neu erfinden".
Für eine Anwendung für Unternehmen ist das DI-Konzept eher eine Architekturebene, die Abhängigkeiten definiert. Um dies weiter zu vereinfachen, können Sie sich dies als ein separates Klassenbibliotheksprojekt vorstellen, das die Abhängigkeitsauflösung durchführt. Die Hauptanwendung hängt von diesem Projekt ab, bei dem sich der Abhängigkeitsauflöser auf andere konkrete Implementierungen und die Abhängigkeitsauflösung bezieht.
Zusätzlich zu "GetType / Create" aus einer Factory benötigen wir meistens mehr Funktionen (Fähigkeit, XML zum Definieren von Abhängigkeiten, Verspotten und Testen von Einheiten usw. zu verwenden). Da Sie sich auf die Strukturkarte bezogen haben, sehen Sie sich die Funktionsliste der Strukturkarte an . Es ist eindeutig mehr als nur das Auflösen einer einfachen Objektzuordnung. Das Rad nicht neu erfinden!
Wenn Sie nur einen Hammer haben, sieht alles aus wie ein Nagel
Abhängig von Ihren Anforderungen und der Art der Anwendung, die Sie erstellen, müssen Sie eine Auswahl treffen. Wenn es nur wenige Projekte gibt (möglicherweise ein oder zwei) und nur wenige Abhängigkeiten aufweist, können Sie einen einfacheren Ansatz wählen. Es ist so, als würde man den ADO .Net-Datenzugriff über Entity Framework für einfache 1 oder 2 Datenbankaufrufe verwenden, wobei die Einführung von EF in diesem Szenario ein Overkill ist.
Aber für ein größeres Projekt oder wenn Ihr Projekt größer wird, würde ich dringend empfehlen, eine DI-Ebene mit einem Framework zu haben und Platz zu schaffen, um das von Ihnen verwendete DI-Framework zu ändern (Verwenden Sie eine Fassade in der Haupt-App (Web-App, Web-API, Desktop) ..usw.).
quelle
Mit einer Factory können Sie verwandte Schnittstellen gruppieren. Wenn die übergebenen Parameter in einer Factory gruppiert werden können, ist dies auch eine gute Lösung
constructor overinjection
, um diesen Code zu betrachten *):Schauen Sie sich den Konstruktor an, Sie müssen nur die
IAddressModelFactory
dort übergeben, also weniger Parameter *):Sie sehen in
CustomerController
vielen übergebenen Parametern: Ja, Sie können dies so sehen,constructor overinjection
aber so funktioniert DI. Und nein, nichts ist falsch mit demCustomerController
.*) Code stammt von nopCommerce.
quelle
In einfachen Worten impliziert die Methode "Abhängigkeitsinjektion gegen Fabrik" einen Push-gegen-Pull-Mechanismus.
Pull-Mechanismus : Klassen sind indirekt von der Factory-Methode abhängig, die wiederum von konkreten Klassen abhängig sind.
Schubmechanismus : Die Root-Komponente kann mit allen abhängigen Komponenten an einem einzigen Ort konfiguriert werden, wodurch ein hoher Wartungsaufwand und eine lose Kopplung gefördert werden.
Bei der Factory-Methode liegt die Verantwortung immer noch bei der Klasse (wenn auch indirekt), um ein neues Objekt zu erstellen, bei dem wie bei der Abhängigkeitsinjektion diese Verantwortung ausgelagert wird (allerdings auf Kosten einer undichten Abstraktion).
quelle
Ich denke, diese sind orthogonal und können zusammen verwendet werden. Lassen Sie mich Ihnen ein Beispiel zeigen, das mir kürzlich bei der Arbeit begegnet ist:
Wir haben das Spring-Framework in Java für DI verwendet. Eine Singleton-Klasse (
Parent
) musste neue Objekte einer anderen Klasse (Child
) instanziieren , und diese hatten komplexe Kollaborateure:In diesem Beispiel müssen Instanzen nur
Parent
empfangenDepX
werden, um sie an denChild
Konstruktor zu übergeben. Probleme damit:Parent
hat mehr WissenChild
als es sollteParent
hat mehr Mitarbeiter als es sollteChild
umfasst das ÄndernParent
Zu diesem Zeitpunkt wurde mir klar, dass ein
Factory
hier perfekt passen würde:Child
Klasse, wie von gesehenParent
Child
, das in der DI-Konfiguration zentralisiert werden kann.Dies ist die vereinfachte
Parent
Klasse und dieChildFactory
Klasse:quelle
Sie verwenden die Abhängigkeitsinjektion, wenn Sie genau wissen, welche Art von Objekten Sie zu diesem Zeitpunkt benötigen. Während Sie im Falle eines Fabrikmusters nur den Prozess des Erstellens von Objekten an die Fabrik delegieren, sind Sie sich nicht sicher, welchen genauen Objekttyp Sie benötigen.
quelle
Ich verwende beide , um eine Inversion Of Control-Strategie mit besserer Lesbarkeit für Entwickler zu erstellen, die sie nach mir warten müssen.
Ich verwende eine Factory, um meine verschiedenen Layer-Objekte (Business, Datenzugriff) zu erstellen.
Ein anderer Entwickler wird dies sehen und beim Erstellen eines Business Layer-Objekts sucht er in BusinessFactory und Intellisense gibt dem Entwickler alle möglichen Business Layer zum Erstellen. Muss das Spiel nicht spielen, finde die Schnittstelle, die ich erstellen möchte.
Diese Struktur ist bereits Inversion Of Control. Ich bin nicht länger für die Erstellung des spezifischen Objekts verantwortlich. Sie müssen jedoch weiterhin die Abhängigkeitsinjektion sicherstellen, um Änderungen problemlos vornehmen zu können. Das Erstellen einer eigenen benutzerdefinierten Abhängigkeitsinjektion ist lächerlich, daher verwende ich Unity. Innerhalb von CreateCarBusiness () bitte ich Unity, aufzulösen, welche Klasse dazu gehört und welche Lebensdauer sie hat.
Meine Code Factory Dependency Injection-Struktur lautet also:
Jetzt habe ich den Vorteil von beiden. Mein Code ist auch für andere Entwickler besser lesbar als für die Bereiche meiner Objekte, die ich verwende, anstatt für die Konstruktorabhängigkeitsinjektion, die nur besagt, dass jedes Objekt verfügbar ist, wenn die Klasse erstellt wird.
Ich verwende dies, um meinen Datenbankdatenzugriff beim Erstellen von Komponententests auf eine benutzerdefinierte codierte Datenzugriffsebene zu ändern. Ich möchte nicht, dass meine Unit-Tests mit Datenbanken, Webservern, E-Mail-Servern usw. kommunizieren. Sie müssen meine Business-Schicht testen, da dort die Intelligenz liegt.
quelle
Die Verwendung der Abhängigkeitsinjektion ist meiner Meinung nach viel besser, wenn Sie: 1. Ihren Code in einer kleinen Partition bereitstellen, da dies beim Entkoppeln eines großen Codes gut funktioniert. 2. Testbarkeit ist einer der Fälle, in denen DI in Ordnung ist, da Sie die nicht entkoppelten Objekte leicht verspotten können. Mit Hilfe von Schnittstellen können Sie jedes Objekt einfach verspotten und testen. 3. Sie können jeden Teil des Programms gleichzeitig überarbeiten, ohne den anderen Teil des Programms codieren zu müssen, da es lose entkoppelt ist.
quelle