576 Stimmen

Dependency Injection vs. Factory Pattern

Die meisten der Beispiele, die für die Verwendung von Dependency Injection angeführt werden, können wir auch mit dem Factory Pattern lösen. Es sieht so aus, als ob der Unterschied zwischen Dependency Injection und Factory bei der Verwendung/Entwicklung verschwommen oder dünn ist.

Jemand hat mir einmal gesagt, dass es darauf ankommt, wie man es benutzt!

Ich habe einmal StructureMap einen DI-Container, um ein Problem zu lösen. Später habe ich ihn so umgestaltet, dass er mit einer einfachen Fabrik funktioniert und die Verweise auf StructureMap entfernt.

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

27 Stimmen

Können sich diese beiden Ansätze nicht gegenseitig ergänzen, indem man Dependency Injection zur Injektion von Fabrikklassen verwendet?

21 Stimmen

Es wäre wirklich schön, wenn diese Frage mit einem Code beantwortet werden könnte! Ich sehe immer noch nicht, wie DI vorteilhaft/unterschiedlich von der Verwendung einer Fabrik für die Erstellung sein würde? Sie müssen nur diese eine Zeile in der Fabrikklasse ersetzen, um zu ändern, welches Objekt/Implementierung erstellt wird?

2 Stimmen

@gideon würde das nicht dazu führen, dass Sie Ihre Anwendung kompilieren müssen, oder zumindest das Modul, das die Fabrikklasse enthält?

33voto

BinMaster Punkte 1

Ein Nachteil von DI ist, dass es Objekte nicht mit Logik initialisieren kann. Wenn ich zum Beispiel eine Figur mit einem zufälligen Namen und Alter erstellen muss, ist DI nicht die richtige Wahl gegenüber dem Fabrikmuster. Mit Fabriken können wir den Zufallsalgorithmus leicht von der Objekterstellung kapseln, was eines der Entwurfsmuster namens "Encapsulate what varies" unterstützt.

24voto

Pup Punkte 9866

Die Verwaltung des Lebenszyklus ist neben der Instanziierung und der Injektion eine der Aufgaben, die die Abhängigkeitscontainer übernehmen. Die Tatsache, dass der Container manchmal einen Verweis auf die Komponenten nach der Instanziierung behält, ist der Grund, warum er als "Container" und nicht als Fabrik bezeichnet wird. Container für Dependency Injection behalten in der Regel nur einen Verweis auf Objekte, für die sie Lebenszyklen verwalten müssen, oder die für zukünftige Injektionen wiederverwendet werden, wie Singletons oder Flyweights. Wenn er so konfiguriert ist, dass er bei jedem Aufruf des Containers neue Instanzen einiger Komponenten erstellt, vergisst der Container das erstellte Objekt normalerweise einfach.

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

21voto

Marcin Szymczak Punkte 10413

Theorie

Es gibt zwei wichtige Punkte zu beachten:

  1. Wer schafft Objekte:
  • [Fabrik]: Sie müssen schreiben, WIE das Objekt erstellt werden soll. Sie haben eine separate Factory-Klasse, die die Erstellungslogik enthält.
  • [Dependency Injection]: In praktischen Fällen wird dies von externen Frameworks durchgeführt (in Java wäre das z.B. spring/ejb/guice). Die Injektion geschieht "auf magische Weise" ohne explizite Erstellung neuer Objekte.
  1. Welche Art von Objekten es verwaltet:
  • [Fabrik]: Normalerweise verantwortlich für die Erstellung von zustandsabhängigen Objekten
  • [Dependency Injections]: Eher zustandslose Objekte erstellen

Praktisches Beispiel für die Verwendung von Factory und Dependency Injection in einem einzigen Projekt

  1. Was wir bauen wollen

Anwendungsmodul zur Erstellung von Aufträgen, die mehrere Einträge enthalten, genannt Auftragszeile.

  1. Architektur

Nehmen wir an, wir wollen die folgende Schichtenarchitektur erstellen:

enter image description here

Domänenobjekte können Objekte sein, die in der Datenbank gespeichert sind. Das Repository (DAO) hilft beim Abrufen von Objekten aus der Datenbank. Dienst bietet API für andere Module. Ermöglicht Operationen auf order Modul.

  1. Domänenebene und Verwendung von Fabriken

Die Entitäten, die sich in der Datenbank befinden werden, sind Order und OrderLine. Ein Auftrag kann mehrere Auftragszeilen haben. Relationship between Order and OrderLine

Jetzt kommt der wichtige Teil der Gestaltung. Sollen Module außerhalb dieses Moduls selbständig OrderLines erstellen und verwalten? Nein. Eine Auftragszeile sollte nur existieren, wenn ein Auftrag mit ihr verbunden ist. Es wäre am besten, wenn Sie die interne Implementierung vor externen Klassen verbergen könnten.

Aber wie erstellt man eine Bestellung ohne Wissen über OrderLines?

Fabrik

Jemand, der eine neue Bestellung erstellen möchte, verwendet OrderFactory (die Details über die Tatsache, wie wir eine Bestellung erstellen, verbergen wird).

enter image description here

So sieht es dann in einer IDE aus. Klassen außerhalb der domain Paket verwendet OrderFactory anstelle des Konstruktors innerhalb Order .

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

OrderRepository und OrderService werden durch das Dependency Injection Framework verwaltet. Das Repository ist für die Verwaltung von CRUD-Operationen in der Datenbank zuständig. Der Dienst injiziert das Repository und verwendet es zum Speichern/Finden der richtigen Domänenklassen.

enter image description here

0 Stimmen

Können Sie das bitte klarstellen? [Factory]: Usually responsible for creation of stateful objects [Dependency Injections] More likely to create stateless objects Ich verstehe nicht, warum

2 Stimmen

Zustandsabhängige Objekte befinden sich wahrscheinlich in der Domänenschicht der Anwendung, in der Sie Ihre Daten auf die Datenbank abbilden, so dass Sie dort in der Regel keine Abhängigkeitsinjektion verwenden. Factory wird oft verwendet, um AggregateRoot aus einem Baum von komplizierten Objekten zu erstellen

16voto

Ich glaube, dass DI eine Art Abstraktionsschicht auf Fabriken ist, aber sie bieten auch Vorteile, die über die Abstraktion hinausgehen. Eine echte Fabrik weiß, wie man einen einzelnen Typ instanziiert und ihn konfiguriert. Eine gute DI-Schicht bietet durch Konfiguration die Möglichkeit, viele Typen zu instanziieren und zu konfigurieren.

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

Wenn Sie jedoch ein Projekt haben, das zahlreiche Typen enthält, deren Implementierungen Sie voraussichtlich häufig ändern werden, bietet Ihnen DI durch seine Konfiguration die Flexibilität, dies zur Laufzeit zu tun, ohne dass Sie Ihre Factories neu kompilieren müssen.

6voto

Kosi2801 Punkte 20758

Mit einem Dependency-Injection-Framework muss der Entwickler die Abhängigkeiten einer Klasseninstanz nicht manuell vorbereiten und festlegen, da alles im Voraus vorbereitet ist.

Bei Fabriken muss der Entwickler dies von Hand tun und die Klasseninstanz unter Verwendung dieser abhängigen Objekte erstellen.

Der Unterschied liegt vor allem in dieser einen Zeile, in der die Fabrik aufgerufen und das konstruierte Objekt abgeholt wird, und im Schreiben der Fabrikmethode, die alles erstellt und einrichtet (obwohl man argumentieren könnte, dass dies bei Frameworks mit Abhängigkeitsinjektion bis zu einem gewissen Grad ebenfalls geschehen muss, indem die Objektbeziehungen verdrahtet und konfiguriert werden).

Bei Fabriken müssen Sie die Fabrik überall dort aufrufen, wo Sie ein solches Objekt benötigen. Bei DI-Frameworks kann man sich meist darauf verlassen, dass das Objekt bereits bei der Erstellung der Klasseninstanz vorhanden ist.

Meiner Meinung nach ist eine Factory-Methode eher statisch, da ihre Implementierung eher feststeht, während ein Dependency-Injection-Framework dynamischer ist, da sich die tatsächliche Zusammensetzung einer Klasseninstanz im laufenden Betrieb leichter ändern kann (z. B. zu Testzwecken).

2 Stimmen

Was Sie beschreiben, ist keine DI. Sie sprechen über DI freamwork, die für Sie die schwere Arbeit der Neuschreibung des Codes in Kompilierzeit machen. Das Muster selbst hat keine Verbindung zu dem, was Sie beschreiben

1 Stimmen

@yehonatanyehezkel hat den Text aktualisiert, um besser auszudrücken, dass sich meine Antwort auf Frameworks und nicht auf Entwurfsmuster bezieht

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X