Abhängigkeits-Injektion gegen Fabrikmuster

Die meisten Beispiele, die für die Verwendung von Dependency Injection angegeben wurden, können wir auch mit dem Factory-Muster lösen. Es sieht so aus, dass der Unterschied zwischen der Abhängigkeitsinjektion und der Fabrik bei der Verwendung / Gestaltung unscharf oder dünn ist.

Einmal hat mir jemand gesagt, dass es einen Unterschied macht, wie man es benutzt!

Ich habe einmal StructureMap einen DI-Container verwendet, um ein Problem zu lösen, später habe ich es so umgestaltet, dass es mit einer einfachen Factory funktioniert und Referenzen auf StructureMap entfernt.

Kann mir jemand sagen, was ist der Unterschied zwischen ihnen und wo was zu verwenden, was ist die beste Praxis hier?

    Wenn Sie eine Factory verwenden, ist Ihr Code immer noch für das Erstellen von Objekten zuständig. Durch DI outsourcen Sie diese Verantwortung an eine andere class oder ein Framework, das von Ihrem Code getrennt ist.

    Ich würde vorschlagen, die Konzepte einfach und klar zu halten. Dependency Injection ist eher ein architektonisches Muster für die lose Kopplung von Softwarekomponenten. Das Factory-Muster ist nur eine Möglichkeit, die Verantwortung für das Erstellen von Objekten anderer classn auf eine andere Entität zu trennen. Das Factory-Muster kann als Werkzeug zum Implementieren von DI aufgerufen werden. Abhängigkeitsinjektion kann auf viele Arten implementiert werden, wie DI unter Verwendung von Konstruktoren, unter Verwendung von Mapping-XML-Dateien usw.

    Abhängigkeitsspritze

    Anstatt die Teile selbst zu instanziieren, fragt ein Auto nach den Teilen, die es braucht, um zu funktionieren.

     class Car { private Engine; private SteeringWheel; private Tires tires; public Car(Engine engine, SteeringWheel wheel, Tires tires) { this.Engine = engine; this.SteeringWheel = wheel; this.Tires = tires; } } 

    Fabrik

    Fügt die Teile zu einem vollständigen Objekt zusammen und verbirgt den konkreten Typ vor dem Aufrufer.

     static class CarFactory { public ICar BuildCar() { Engine engine = new Engine(); SteeringWheel steeringWheel = new SteeringWheel(); Tires tires = new Tires(); ICar car = new RaceCar(engine, steeringWheel, tires); return car; } } 

    Ergebnis

    Wie Sie sehen können, ergänzen sich Fabriken und DI.

     static void Main() { ICar car = CarFactory.BuildCar(); // use car } 

    Erinnerst du dich an Goldlöckchen und die drei Bären? Nun, die Abhängigkeitsinjektion ist irgendwie so. Hier sind drei Möglichkeiten, das Gleiche zu tun.

     void RaceCar() // example #1 { ICar car = CarFactory.BuildCar(); car.Race(); } void RaceCar(ICarFactory carFactory) // example #2 { ICar car = carFactory.BuildCar(); car.Race(); } void RaceCar(ICar car) // example #3 { car.Race(); } 

    Beispiel # 1 – Dies ist das Schlimmste, weil es die Abhängigkeit vollständig verbirgt. Wenn Sie die Methode als Black Box betrachteten, hätten Sie keine Ahnung, dass es ein Auto benötigt.

    Beispiel # 2 – Das ist ein bisschen besser, denn jetzt wissen wir, dass wir ein Auto brauchen, da wir in einer Autofabrik vorbeifahren. Aber dieses Mal gehen wir zu viel durch, da die ganze Methode, die benötigt wird, ein Auto ist. Wir fahren in einer Fabrik vorbei, nur um das Auto zu bauen, wenn das Auto außerhalb der Methode gebaut und übergeben werden konnte.

    Beispiel # 3 – Dies ist ideal, weil die Methode genau nach dem fragt , was sie benötigt. Nicht zu viel oder zu wenig. Ich muss keine MockCarFactory schreiben, nur um MockCars zu erstellen, ich kann den Mock direkt eingeben. Es ist direkt und die Schnittstelle lügt nicht.

    Dieser Google Tech Talk von Misko Hevery ist erstaunlich und ist die Grundlage dessen, von dem ich mein Beispiel abgeleitet habe. http://www.youtube.com/watch?v=XcT4yYu_TTs

    Es gibt Probleme, die mit der Abhängigkeitsinjektion leicht zu lösen sind und die nicht so einfach mit einer Reihe von Fabriken getriggers werden können.

    Ein Teil des Unterschieds zwischen einer Inversion von Kontrolle und Abhängigkeitsinjektion (IOC / DI) einerseits und einem Service Locator oder einer Reihe von Fabriken (Fabrik) andererseits ist:

    IOC / DI ist ein vollständiges Ökosystem von Domänenobjekten und Diensten an und für sich. Es richtet alles auf die von Ihnen angegebene Weise für Sie ein. Ihre Domänenobjekte und -Dienste werden vom Container erstellt und bauen sich nicht selbst auf: Sie haben daher keine Abhängigkeiten vom Container oder von Fabriken. IOC / DI ermöglicht ein extrem hohes Maß an Konfigurierbarkeit, mit der gesamten Konfiguration an einem einzigen Ort (Aufbau des Containers) auf der obersten Ebene Ihrer Anwendung (GUI, Web-Front-End).

    Factory abstrahiert etwas von der Konstruktion Ihrer Domain-Objekte und -Dienste. Aber Domänenobjekte und Dienste sind immer noch dafür verantwortlich herauszufinden, wie sie sich selbst konstruieren und wie sie all die Dinge bekommen, von denen sie abhängig sind. Alle diese “aktiven” Abhängigkeiten filtern alle Schichten in Ihrer Anwendung durch. Es gibt keinen einzigen Ort, um alles zu konfigurieren.

    Ein Nachteil von DI ist, dass Objekte mit Logik nicht initialisiert werden können. Zum Beispiel, wenn ich ein Zeichen erstellen muss, das einen zufälligen Namen und ein zufälliges Alter hat, ist DI nicht die Wahl des Fabrikmusters. Mit Fabriken können wir den Zufallsalgorithmus leicht aus der Objekterzeugung kapseln, die eines der Entwurfsmuster mit dem Namen “Encapsulate what variables” unterstützt.

    Das Life-Cycle-Management ist eine der Zuständigkeiten, die neben der Instanziierung und Einspeisung auch von Containern übernommen werden. Die Tatsache, dass der Container manchmal nach der Instanziierung einen Verweis auf die Komponenten behält, ist der Grund, warum er als “Container” und nicht als Fabrik bezeichnet wird. Dependency-Injektionscontainer enthalten normalerweise nur einen Verweis auf Objekte, die für die Verwaltung von Lebenszyklen benötigt werden oder die für zukünftige Injektionen wie Singletons oder Fliehgewichte wiederverwendet werden. Wenn der Container so konfiguriert ist, dass er für jeden Aufruf des Containers neue Instanzen bestimmter Komponenten erstellt, vergisst er normalerweise nur das erstellte Objekt.

    Von: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html

    Der Grund dafür, dass Dependency Injection (DI) und Factory Patterns ähnlich sind, liegt darin, dass es sich um zwei Implementierungen von Inversion of Control (IoC) handelt, bei der es sich um eine Softwarearchitektur handelt. Einfach gesagt, es sind zwei Lösungen für das gleiche Problem.

    Um die Frage zu beantworten, besteht der Hauptunterschied zwischen dem Factory-Muster und DI darin, wie die Objektreferenz erhalten wird. Mit Abhängigkeitsinjektion, wie der Name sagt, wird die Referenz injiziert oder Ihrem Code gegeben. Mit Factory-Muster 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 class oder dem Typ der Objektreferenz, die von dem Code verwendet wird.

    Es ist erwähnenswert, dass Factory-Muster (oder tatsächlich Factory-Muster, die Factories sind, die neue Factorys zurückgeben, die Objektreferenzen zurückgeben) geschrieben werden können, um den Typ oder die class des Objekts, das zur Laufzeit angefordert wird, dynamisch auszuwählen oder zu verknüpfen. Dies macht sie sehr ähnlich (noch mehr als DI) zum Service Locator-Muster, das eine andere Implementierung des IoC ist.

    Das Factory-Design-Muster ist ziemlich alt (in Bezug auf Software) und gibt es schon seit einiger Zeit. Seit der kürzlichen Popularität des architektonischen Musters IoC hat es eine Wiederauferstehung.

    Ich denke, wenn es um IoC-Designmuster geht: Injektoren werden injiziert, Lokatoren werden lokalisiert und die Fabriken wurden umstrukturiert.

    Ich glaube, DI ist eine Art von Abstraktionsschicht auf Fabriken, aber sie bieten auch Vorteile jenseits der Abstraktion. Eine echte Fabrik kann einen einzelnen Typ instanziieren und konfigurieren. Eine gute DI-Schicht bietet die Möglichkeit, durch Konfiguration viele Typen zu instanziieren und zu konfigurieren.

    Offensichtlich ist das Fabrikmuster für ein Projekt mit ein paar einfachen Typen, die eine relativ stabile Geschäftslogik in ihrer Konstruktion erfordern, einfach zu verstehen, zu implementieren und funktioniert gut.

    OTOH, wenn Sie ein Projekt haben, das zahlreiche Typen enthält, deren Implementierungen Sie häufig ändern möchten, gibt Ihnen DI die Flexibilität, dies zur Laufzeit zu tun, ohne Ihre Fabriken neu kompilieren zu müssen.

    Ich weiß, dass diese Frage alt ist, aber ich möchte meine fünf Cents hinzufügen,

    Ich denke, dass Dependency Injection (DI) in vielerlei Hinsicht wie ein konfigurierbares Factory Pattern (FP) ist, und in diesem Sinne wird alles, was man mit DI machen kann, mit einer solchen Fabrik möglich sein.

    Wenn Sie zum Beispiel Spring verwenden, haben Sie die Möglichkeit, Ressourcen automatisch zu löschen (DI) oder etwas in der Art zu tun:

     MyBean mb = ctx.getBean("myBean"); 

    Und dann benutze diese “mb” -Instanz, um etwas zu tun. Ist das nicht ein Aufruf an eine Fabrik, die dir eine Instanz zurückgibt?

    Der einzige wirkliche Unterschied, den ich zwischen den meisten der FP-Beispiele feststellen kann, ist, dass Sie konfigurieren können, was “myBean” in einem XML oder einer anderen class ist, und ein Framework funktioniert wie die Factory, aber ansonsten ist es das Gleiche und Sie kann eine Factory haben, die eine Konfigurationsdatei liest oder die Implementierung bekommt, wie sie benötigt.

    Und wenn du mich nach meiner Meinung fragst (und ich weiß, dass du es nicht getan hast), glaube ich, dass DI dasselbe tut, aber der Entwicklung mehr Komplexität hinzufügt, warum?

    Nun, für eine Sache, für Sie zu wissen, welche Implementierung für jede Bean verwendet wird, die Sie mit DI authorisieren, müssen Sie zur Konfiguration selbst gehen.

    aber … was ist mit dem Versprechen, dass Sie die Implementierung des Objekts, das Sie verwenden, nicht kennen müssen? Pfft! ernst? Wenn Sie einen solchen Ansatz verwenden … sind Sie nicht derselbe, der die Implementierung schreibt? Und selbst wenn du es nicht tust, bist du nicht fast ständig dabei, wie die Implementierung das tut, was sie tun soll?

    und für eine letzte Sache ist es egal, wie viel ein DI-Framework Ihnen verspricht , dass Sie Dinge davon entkoppeln , ohne Abhängigkeiten zu ihren classn, wenn Sie ein Framework verwenden, bauen Sie alles um es herum, wenn Sie müssen Ändern Sie den Ansatz oder das Framework wird es keine leichte Aufgabe sein … EVER! … aber da Sie alles um diesen bestimmten Rahmen herum gebaut haben, anstatt sich Gedanken darüber zu machen, was die beste Lösung für Ihr Geschäft ist, dann werden Sie mit einem Problem konfrontiert, wenn Sie das tun.

    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 Frameworks, von denen ich weiß, dass Sie das nicht tun können, müssen Sie verlassen Alles perfekt in der Konfiguration zur Entwicklungszeit und wenn Sie einen anderen Ansatz benötigen.

    Also, wenn ich eine class habe, die in zwei Bereichen in der gleichen Anwendung anders funktioniert (sagen wir zwei Firmen einer Holding), muss ich das Framework so konfigurieren, dass zwei verschiedene Beans erstellt werden, und meinen Code so anpassen, dass jeder verwendet wird. Ist das nicht so, als würde ich einfach so etwas schreiben:

     MyBean mb = MyBeanForEntreprise1(); //In the classes of the first enterprise MyBean mb = MyBeanForEntreprise2(); //In the classes of the second enterprise 

    das gleiche wie folgt:

     @Autowired MyBean mbForEnterprise1; //In the classes of the first enterprise @Autowired MyBean mbForEnterprise2; //In the classes of the second enterprise 

    Und das:

     MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise1"); //In the classes of the first enterprise MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise2"); //In the classes of the second enterprise 

    In jedem Fall müssen Sie etwas in Ihrer Anwendung ändern, ob classn oder Konfigurationsdateien, aber Sie müssen es erneut bereitstellen.

    Wäre es nicht schön, einfach so etwas zu tun:

     MyBean mb = (MyBean)MyFactory.get("mb"); 

    Und auf diese Weise setzen Sie den Code der Factory, um die richtige Implementierung zur Laufzeit abhängig vom angemeldeten Benutzerunternehmen zu erhalten? Das wäre jetzt hilfreich. Sie könnten einfach ein neues Jar mit den neuen classn hinzufügen und die Regeln vielleicht sogar zur Laufzeit setzen (oder eine neue Konfigurationsdatei hinzufügen, wenn Sie diese Option offen lassen), keine Änderungen an vorhandenen classn. 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 Switch niemals zur Laufzeit ausführen muss, also konfiguriere ich die App, und wenn ich die class erben oder eine andere Implementierung verwende, ändere ich einfach die Konfiguration und redeploy. Ok, das kann auch mit einer Fabrik gemacht werden. Und ehrlich gesagt, wie oft machst du das? Vielleicht nur, wenn Sie eine App haben, die irgendwo anders in Ihrem Unternehmen verwendet wird, und Sie werden den Code an ein anderes Team weitergeben, und sie werden solche Dinge tun. Aber hey, das kann auch mit der Fabrik gemacht werden und wäre noch besser mit einer dynamischen Fabrik !!

    Wie auch immer, der Kommentarbereich ist offen für dich, um mich zu töten.

    Theorie

    Es gibt zwei wichtige Punkte zu beachten:

    1. Wer erstellt Objekte?

      • [Factory]: Sie müssen schreiben, wie das Objekt erstellt werden soll. Sie haben eine separate Factory-class, die eine Erstellungslogik enthält.
      • [Dependency Injection]: In praktischen Fällen werden externe Frameworks verwendet (zum Beispiel in Java, das wäre spring / ejb / guice). Die Injektion geschieht “magisch” ohne explizite Erstellung neuer Objekte
    2. Welche Art von Objekten verwaltet es:

      • [Factory]: Normalerweise verantwortlich für die Erstellung von statusbehafteten Objekten
      • [Abhängigkeitsinjektionen] Wahrscheinlicher, statusfreie Objekte zu erstellen

    Praktisches Beispiel für die Verwendung von Factory- und Abhängigkeitsinjektionen in einem Projekt

    1. Was wir bauen wollen

    Anwendungsmodul zum Erstellen einer Bestellung, die mehrere Einträge enthält, genannt Bestellposten.

    1. Die Architektur

    Nehmen wir an, wir möchten folgende Layer-Architektur erstellen:

    Bildbeschreibung hier eingeben

    Domänenobjekte können Objekte sein, die in der database gespeichert sind. Repository (DAO) hilft beim Abruf von Objekten aus der database. Der Service stellt API für andere Module bereit. Läuft für Operationen auf order

    1. Domain Layer und Nutzung von Fabriken

    Entitäten, die in der database enthalten sind, sind Order und OrderLine. Der Auftrag kann mehrere OrderLines enthalten. Beziehung zwischen Order und OrderLine

    Jetzt kommt wichtiger Designteil. Sollten Module außerhalb von diesem OrderLines selbst erstellen und verwalten? Nein. Bestellposten sollten nur existieren, wenn Sie einen Auftrag damit verbunden haben. Es wäre am besten, wenn Sie die interne Implementierung für externe classn ausblenden könnten.

    Aber wie erstellt man Order ohne Wissen über OrderLines?

    Fabrik

    Jemand, der eine neue Bestellung erstellen möchte, hat OrderFactory verwendet (was Details darüber verbergen wird, wie wir Order erstellen).

    Bildbeschreibung hier eingeben

    So wird es in der IDE aussehen. classn außerhalb des domain verwenden OrderFactory anstelle des Konstruktors in Order

    1. Dependency Injection Dependency Injection wird häufiger bei zustandslosen Schichten wie Repository und Service verwendet.

    OrderRepository und OrderService werden vom Framework für die Abhängigkeitsinjektion verwaltet. Das Repository ist für die Verwaltung der CRUD-Vorgänge in der database zuständig. Der Dienst fügt Repository hinzu und verwendet es, um korrekte Domänenklassen zu speichern / zu finden.

    Bildbeschreibung hier eingeben

    Bei der Dependency-Injection muss der Client seine Abhängigkeiten nicht selbstständig abrufen, er ist bereits vorbereitet.

    Bei Fabriken muss jemand diese aufrufen, um die generierten Objekte dorthin zu bringen, wo sie benötigt werden.

    Der Unterschied liegt hauptsächlich in dieser Zeile, in der der Aufruf der Factory und das Abrufen des konstruierten Objekts erfolgt.

    Aber bei Fabriken muss man diese 1 Zeile überall dort schreiben, wo man ein solches Objekt benötigt. Mit DI müssen Sie nur einmal die Verdrahtung (Beziehung zwischen Verwendung und erzeugtem Objekt) erstellen und sich darauf verlassen, dass das Objekt überallhin vorhanden ist. Auf der anderen Seite erfordert DI oft ein bisschen mehr (was vom Rahmen abhängt) auf der Vorbereitungsseite.

    IOC ist ein Konzept, das auf zwei Arten implementiert wird. Abhängigkeitserzeugung und Abhängigkeitsinjektion, Factory / Abstract factory sind das Beispiel für die Erstellung von Abhängigkeiten. Abhängigkeitsinjektion ist Konstruktor, Setter und Schnittstelle. Der core von IOC besteht darin, nicht von den konkreten classn abzuhängen, sondern das Abstrakte von Methoden zu definieren (sagen wir eine Schnittstelle / abstrakte class) und dieses Abstract zu verwenden, um die Methode der konkreten class aufzurufen. Wie Factory-Muster geben Sie die Basisklasse oder Schnittstelle zurück. Ahnliche Injection-Injection-Verwendung Basisklasse / Schnittstelle zum Festlegen des Werts für Objekte.

    Ich hatte die gleiche Frage, sobald ich über DI gelesen habe und auf diesem Posten gelandet bin. Letztendlich habe ich das verstanden, aber korrigiere mich bitte, wenn ich falsch liege.

    “Vor langer Zeit gab es kleine Königreiche mit eigenen Regierungsorganen, die Entscheidungen auf der Grundlage ihrer eigenen geschriebenen Regeln kontrollierten und trafen. Später bildete sich eine große Regierung, die all diese kleinen Regierungsorgane abschaffte, die ein Regelwerk (Verfassung) haben und durch Gerichte umgesetzt werden.”

    Die Regierungsorgane der kleinen Königreiche sind “Fabriken”

    Die große Regierung ist der “Dependency Injector”.

    Sie können sich diesen Link für einen Vergleich der beiden (und anderer) Ansätze in einem realen Beispiel ansehen.

    Wenn sich die Anforderungen ändern, ändern Sie im Grunde mehr Code, wenn Sie Factors anstelle von DI verwenden.

    Dies gilt auch für die manuelle DI (dh wenn es kein externes Framework gibt, das die Abhängigkeiten zu Ihren Objekten bereitstellt, Sie diese jedoch in jedem Konstruktor übergeben).

    Ich glaube, dass DI eine Möglichkeit ist, eine Bean zu konfigurieren oder zu instantiieren. Die DI kann auf viele Arten wie Konstruktor, Setter-Getter usw. ausgeführt werden.

    Das Factory-Muster ist nur eine weitere Möglichkeit, Bohnen zu instanziieren. Dieses Muster wird hauptsächlich verwendet, wenn Sie Objekte mithilfe des Factory-Entwurfsmusters erstellen müssen, da Sie bei der Verwendung dieses Musters die Eigenschaften einer Bean nicht konfigurieren, sondern nur das Objekt instanziieren.

    Überprüfen Sie diesen Link: Abhängigkeitsinjektion

    Binoj,

    Ich glaube nicht, dass Sie sich für eines entscheiden müssen.

    Der Vorgang des Verschiebens einer abhängigen class oder Schnittstelle zu einem classnkonstruktor oder einem Setter folgt dem DI-Muster. Das Objekt, das Sie an den Konstruktor oder das Set übergeben, kann mit Factory implementiert werden.

    Wann zu verwenden? Verwenden Sie das Muster oder die Muster, die sich in Ihrem Entwickler-Steuerhaus befinden. Worüber sie sich am wohlsten fühlen und am leichtesten zu verstehen sind.

    Meine Gedanken:

    Dependency Injection: Übergeben Sie Kollaborateuren 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.

    Ein Injection Framework ist eine Implementierung des Factory Patterns.

    Alles hängt von Ihren Anforderungen ab. Wenn Sie das Factory-Muster in einer Anwendung implementieren müssen, ist es sehr wahrscheinlich, dass Ihre Anforderungen von einer der unzähligen Implementierungen von Injection-Frameworks erfüllt werden.

    Sie sollten nur Ihre eigene Lösung implementieren, 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, welche Implementierung Sie verwenden sollten, sind nicht so grundlegend wichtig wie das Verständnis der Architekturanforderungen Ihrer Anwendung.

    Fabrik Design Muster

    Das Fabrikdesignmuster ist gekennzeichnet durch

    • Eine Schnittstelle
    • Implementierungsklassen
    • Eine Fabrik

    Sie können einige Dinge beobachten, wenn Sie sich selbst in Frage stellen

    • Wann erstellt die Factory ein Objekt für die Implementierungsklassen – Laufzeit oder Kompilierzeit?
    • Was, wenn Sie die Implementierung zur Laufzeit wechseln möchten? – Nicht möglich

    Diese werden durch Dependency-Injektion behandelt.

    Abhängigkeitsspritze

    Sie können auf verschiedene Arten Abhängigkeiten injizieren. Zur Vereinfachung lässt sich mit Interface Injection fortfahren

    In DI erstellt der Container die erforderlichen Instanzen und “injiziert” sie in das Objekt.

    Damit entfällt die statische Instanziierung.

    Beispiel:

     public class MyClass{ MyInterface find= null; //Constructor- During the object instantiation public MyClass(MyInterface myInterface ) { find = myInterface ; } public void myMethod(){ find.doSomething(); } } 

    Von einem Nennwert sehen sie gleich aus

    In sehr einfachen Worten, Factory Pattern, ein Creational Pattern hilft uns, ein Objekt zu erstellen – “Definieren Sie eine Schnittstelle zum Erstellen eines Objekts”. Wenn wir einen Objekttyp mit einem Schlüsselwert haben (zB Dictionary), den Schlüssel an Factory übergeben (ich beziehe mich auf das Simple Factory Pattern), können Sie den Type auflösen. Job erledigt! Das Dependency Injection Framework (wie Structure Map, Ninject, Unity … etc) scheint das gleiche zu tun.

    Aber … “Erfinde das Rad nicht neu”

    Aus architektonischer Sicht ist es eine bindende Schicht und “erfinde das Rad nicht neu”.

    Für eine Unternehmensanwendung ist das Konzept von DI eher eine Architekturschicht, die Abhängigkeiten definiert. Um dies weiter zu vereinfachen, können Sie sich dies als separates Classlibrary-Projekt vorstellen, das die Abhängigkeit triggers. Die Hauptanwendung hängt von diesem Projekt ab, in dem sich der Dependency-Resolver auf andere konkrete Implementierungen und auf die Abhängigkeitsauflösung bezieht.

    Zusätzlich zu “GetType / Create” von einer Factory benötigen wir meistens mehr functionen (Möglichkeit, XML zu verwenden, um Abhängigkeiten zu definieren, Mocking und Komponententests usw.). Da Sie auf Strukturansicht verwiesen haben, sehen Sie sich die Strukturübersicht an . Es ist deutlich mehr als nur einfaches Objekt Mapping zu lösen. Erfinde das Rad nicht neu!

    Wenn alles, was Sie haben, ein Hammer ist, sieht alles wie ein Nagel aus

    Abhängig von Ihren Anforderungen und der Art der Anwendung, die Sie erstellen, müssen Sie eine Auswahl treffen. Wenn es nur wenige Projekte (vielleicht ein oder zwei …) und wenig Abhängigkeiten gibt, können Sie einen einfacheren Ansatz wählen. Es ist so, als würde man ADO .Net-Datenzugriff über Entity Framework für einfache 1 oder 2 databaseaufrufe verwenden, bei denen 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 Ihnen sehr empfehlen, eine DI-Schicht 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) ..etc.).

    Ich glaube, 3 wichtige Aspekte regeln Objekte und ihre Verwendung:
    1. Instanziierung (einer class zusammen mit der Initialisierung, falls vorhanden).
    2. Injektion (der so geschaffenen Instanz), wo sie benötigt wird.
    3. Lebenszyklusmanagement (der so geschaffenen Instanz).

    Unter Verwendung des Factory-Musters wird der erste Aspekt (Instanziierung) erreicht, aber die verbleibenden zwei sind fraglich. Die class, die andere Instanzen verwendet, muss die Fabriken fest codieren (anstatt Instanzen erstellt zu werden), wodurch lose Kopplungsfähigkeiten verhindert werden. Darüber hinaus wird die Lebenszyklusverwaltung von Instanzen zu einer Herausforderung in einer großen Anwendung, in der eine Fabrik an mehreren Stellen verwendet wird (insbesondere wenn die Fabrik den Lebenszyklus der Instanz, die sie zurückgibt, nicht verwaltet, wird sie hässlich).

    Bei Verwendung eines DI (des IoC-Musters) hingegen werden alle 3 außerhalb des Codes (zu dem DI-Container) abstrahiert und die verwaltete Bean benötigt nichts über diese Komplexität. Loose Coupling , ein sehr wichtiges architektonisches Ziel, kann ruhig und komfortabel erreicht werden. Ein anderes wichtiges architektonisches Ziel, die Trennung von Belangen, kann viel besser erreicht werden als Fabriken.

    Während die Fabriken für kleine Anwendungen geeignet sein können, wäre es für große Fabriken besser, DI über Fabriken zu wählen.

    Die meisten Antworten hier erklären konzeptionelle Unterschiede und Implementierungsdetails von beiden. Ich konnte jedoch keine Erklärung für die unterschiedliche Anwendung finden, die die IMO am wichtigsten ist und nach der das OP gefragt wurde. Lassen Sie mich dieses Thema erneut eröffnen …

    Einmal hat mir jemand gesagt, dass es einen Unterschied macht, wie man es benutzt!

    Genau. In 90% der Fälle können Sie Objektreferenzen entweder über Factory oder DI erhalten und normalerweise landen Sie bei Letzteren. In weiteren 10% Fällen ist die Verwendung von Factory nur der richtige Weg . Zu diesen Fällen gehört das Abrufen von Objekten durch Variable bei Laufzeitparametern. So was:

     IWebClient client = factoryWithCache.GetWebClient(url: "stackoverflow.com", useCookies: false, connectionTimeout: 120); 

    In diesem Fall ist es nicht möglich, einen client von DI zu erhalten (oder erfordert zumindest eine hässliche Problemumgehung). Also als eine allgemeine Regel, um eine Entscheidung zu treffen: Wenn eine Abhängigkeit ohne irgendwelche Laufzeit-berechneten Parameter erhalten werden kann, wird DI bevorzugt, ansonsten benutze Factory.

    Mit einer Fabrik können Sie verwandte Schnittstellen gruppieren. Wenn also die übergebenen Parameter in einer Fabrik gruppiert werden können, dann ist dies auch eine gute Lösung für die constructor overinjection Sehen Sie sich diesen Code an *):

     public AddressModelFactory(IAddressAttributeService addressAttributeService, IAddressAttributeParser addressAttributeParser, ILocalizationService localizationService, IStateProvinceService stateProvinceService, IAddressAttributeFormatter addressAttributeFormatter) { this._addressAttributeService = addressAttributeService; this._addressAttributeParser = addressAttributeParser; this._localizationService = localizationService; this._stateProvinceService = stateProvinceService; this._addressAttributeFormatter = addressAttributeFormatter; } 

    Schauen Sie sich den Konstruktor an, Sie müssen nur die IAddressModelFactory dort übergeben, also weniger Parameter *):

      public CustomerController(IAddressModelFactory addressModelFactory, ICustomerModelFactory customerModelFactory, IAuthenticationService authenticationService, DateTimeSettings dateTimeSettings, TaxSettings taxSettings, ILocalizationService localizationService, IWorkContext workContext, IStoreContext storeContext, ICustomerService customerService, ICustomerAttributeParser customerAttributeParser, ICustomerAttributeService customerAttributeService, IGenericAttributeService genericAttributeService, ICustomerRegistrationService customerRegistrationService, ITaxService taxService, CustomerSettings customerSettings, AddressSettings addressSettings,... 

    Sie sehen in CustomerController eine Menge Parameter übergeben, ja Sie können dies als constructor overinjection aber so funktioniert DI. Und nichts ist falsch mit dem CustomerController .

    *) Code ist von nopCommerce.

    In einfachen Worten bedeutet Dependency Injection vs Factory-Methode Push / Pull-Mechanismus.

    Mit Pull-Mechanismus: class indirekt Abhängigkeit von Factory-Methode, die wiederum Abhängigkeit von konkreten classn haben.

    With Push mechanism : Root component can be configured with all dependent components in a single location and thus promoting high maintenance and loose coupling.

    With Factory method responsibility still lies with class (though indirectly) to create new object where as with dependency injection that responsibility is outsourced (at the cost of leaking abstraction though)

    I think these are orthogonal and can be used together. Let me show you an example I recently came across at work:

    We were using the Spring framework in Java for DI. A singleton class ( Parent ) had to instantiate new objects of another class ( Child ), and those had complex collaborators:

     @Component class Parent { // ... @Autowired Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) { this.dep1 = dep1; this.dep2 = dep2; } void method(int p) { Child c = new Child(dep1, dep2, ..., depN, p); // ... } } 

    In this example, Parent has to receive DepX instances only to pass them to the Child constructor. Problems with this:

    1. Parent has more knowledge of Child than it should
    2. Parent has more collaborators than it should
    3. Adding dependencies to Child involves changing Parent

    This is when I realized a Factory would fit here perfectly:

    1. It hides all but the true parameters of the Child class, as seen by Parent
    2. It encapsulates the knowledge of creating a Child , which can be centralized in the DI configuration.

    This is the simplified Parent class and the ChildFactory class:

     @Component class Parent { // ... @Autowired Parent(ChildFactory childFactory) { this.childFactory = childFactory; } void method(int p) { Child c = childFactory.newChild(p); // ... } } @Component class ChildFactory { // ... @Autowired Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) { this.dep1 = dep1; this.dep2 = dep2; // ... this.depN = depN; } Child newChild(int p) { return new Child(dep1, dep2, ..., depN, p); } } 

    I use both to create an Inversion Of Control strategy with more readability for developers who need to maintain it after me.

    I use a Factory to create my different Layer objects (Business, Data Access).

     ICarBusiness carBusiness = BusinessFactory.CreateCarBusiness(); 

    Another developer will see this and when creating an Business Layer object he looks in BusinessFactory and Intellisense gives the developer all the possible Business Layers to create. Doesn’t have to play the game, find the Interface I want to create.

    This structure is already Inversion Of Control. I am no longer responsible for creating the specific object. But you still need to ensure Dependency Injection to be able to change things easily. Creating your own custom Dependency Injection is ridiculous, so I use Unity. Within the CreateCarBusiness() I ask Unity to Resolve which class belongs to this and it’s lifetime.

    So my code Factory Dependency Injection structure is:

     public static class BusinessFactory { public static ICarBusiness CreateCarBusiness() { return Container.Resolve(); } } 

    Now I have the benefit of both. My code is also more readable for other developers as towards scopes of my objects I use, instead of Constructor Dependency Injection which just says every object is available when the class is created.

    I use this to change my Database Data Access to a custom coded Data Access layer when I create Unit Tests. I don’t want my Unit Tests to communicate with databases, webservers, e-mail servers etc. They need to test my Business Layer because that’s where the intelligence is.

    Using dependency injection is much better in my opinion if you are: 1. deploying your code in small partition, because it handles well in decoupling of one big code. 2. testability is one of the case DI is ok to use because you can mock easily the non decoupled objects. with the use of interfaces you can easily mock and test each objects. 3. you can simultaneously revised each part of the program without needing to code the other part of it since its loosely decoupled.