Aus den "Gang of Four" -Designmustern ergibt sich die Factory-Methode:
class Factory(product)
case product
when a
new A
when b
new B
when c
new C
end
new Factory(a)
Warum ist das sinnvoller als mit drei Klassen, a
, b
, und c
und sie einzeln aufrufen?
Antworten:
Weil dein Beispiel nicht kompliziert genug ist. Für solch ein einfaches Szenario ist es nicht einmal sinnvoll, ein erweitertes Muster zu verwenden.
Wenn Sie jedoch mehr als das Produkt wissen müssen, um A, B oder C zu konstruieren, und keinen direkten Zugriff auf dieses Wissen haben, ist es nützlich. Dann nutzen Sie die Fabrik als Wissenszentrum für die Herstellung der benötigten Objekte.
Vielleicht benötigen diese Objekte einen Verweis auf ein Objekt X, das die Factory bereitstellen kann, aber Ihr Code an der Stelle, an der Sie A, B oder C konstruieren möchten, kann oder sollte keinen Zugriff auf X haben. Vielleicht, wenn Sie X haben Sie erstellen A und B, aber wenn Sie Y-Typ haben, dann erstellen Sie C.
Bedenken Sie auch, dass einige Objekte möglicherweise 20 Abhängigkeiten benötigen, um erstellt zu werden. was dann? Es könnte problematisch sein, diese Abhängigkeiten an einem Ort zu suchen, an dem sie nicht zugänglich sein sollten.
quelle
Ein Fabrikmuster ist normalerweise komplexer. Eine Factory entscheidet nach bestimmten Kriterien, welche Instanz erstellt / zurückgegeben werden soll. Wenn Sie die Factory nicht verwenden, wird dieser Code an mehreren Stellen im Code wiederholt verwendet.
Betrachten Sie als Beispiel Folgendes: Sie müssen Daten aus einer Datenbank laden, haben jedoch eine zentrale Datenbank für die Integration mit vielen Daten und eine kleinere im Speicher auf jedem Entwicklungs-PC. In Ihrem Code fordern Sie eine Factory auf, ein DB-Handle zu erhalten, und die Factory gibt eines davon zurück, abhängig von z. B. einer Konfigurationsdatei.
quelle
Das Factory-Methodenmuster abstrahiert den Entscheidungsprozess von der aufrufenden Klasse. Dies hat mehrere Vorteile:
Wiederverwendung. Wenn ich an vielen Stellen instanziieren möchte, muss ich meinen Zustand nicht wiederholen. Wenn ich also eine neue Klasse hinzufüge, riskiere ich nicht, eine zu verpassen.
Unit-Testbarkeit. Ich kann 3 Tests für die Factory schreiben, um sicherzustellen, dass sie die richtigen Typen unter den richtigen Bedingungen zurückgibt. Dann muss meine aufrufende Klasse nur getestet werden, um festzustellen, ob sie die Factory aufruft, und dann die erforderlichen Methoden für die zurückgegebene Klasse. Es muss nichts über die Implementierung der Fabrik selbst oder die konkreten Klassen wissen.
Erweiterbarkeit. Wenn jemand entscheidet, dass wir dieser Factory eine neue Klasse D hinzufügen müssen, muss keiner der aufrufenden Codes, weder Unit-Tests noch Implementierung, mitgeteilt werden. Wir erstellen einfach eine neue Klasse D und erweitern unsere Fabrikmethode. Dies ist die eigentliche Definition des Open-Closed-Prinzips .
Sie können sogar eine neue Factory-Klasse erstellen und diese Hot-Swap-fähig machen, wenn die Situation dies erfordert - beispielsweise, wenn Sie Klasse D beim Testen ein- und ausschalten möchten. Ich bin nur einmal auf diese Situation gestoßen, aber sie war äußerst nützlich.
Wie bereits erwähnt, ist das Factory-Pattern nicht immer der richtige Weg. Aber wo immer Sie bedingte Instanziierung sehen, sollten Sie einen Moment darüber nachdenken.
quelle
Die wichtigsten Vorteile des Factory-Musters sind zweierlei:
Die Stellen, an denen eine Implementierung des Produkts erforderlich ist, müssen nicht wissen, wie sie erstellt werden. Die Fabrik hält diese Informationen.
Möchten Sie wissen, welche Argumente an den jeweiligen Konstruktor übergeben werden sollen? Oder welche Abhängigkeiten musst du einspritzen? Oder wie kann die Implementierungsklasse bei der Datenbank registriert werden, nachdem sie vollständig konfiguriert wurde? Nein? Lassen Sie die Fabrik sich um all das Zeug kümmern.
Die Stellen, die eine Implementierung des Produkts benötigen, müssen zum Zeitpunkt der Modulbeschreibung (dh zum Zeitpunkt der Kompilierung) nicht wissen, wie die Implementierungsklasse heißt.
Es
a
muss also nichts damit zu tun habenA
; Das „was zu bauen ist“ kann anhand der gewünschten nicht-funktionalen Eigenschaften und nicht nur des Namens beschrieben werden. Das ist viel flexibler.Der Nachteil ist, dass Sie bei der Verwendung einer Fabrik komplexer werden, wenn Sie wissen, was zu machen ist und wie es zu tun ist. Die Lösung dafür ist jedoch einfach: Verwenden Sie keine Fabrik, wenn sie keinen Sinn ergibt!
quelle
Ich würde gerne über Designmuster nachdenken, in denen Klassen als „Menschen“ verstanden werden, und Muster sind Wege, wie Menschen miteinander reden.
Für mich ist das Fabrikmuster also wie eine Personalagentur. Sie haben jemanden, der eine variable Anzahl von Arbeitern benötigt. Diese Person kann einige Informationen kennen, die sie in den Leuten benötigt, die sie anstellt, aber das ist es.
Wenn sie also einen neuen Mitarbeiter brauchen, rufen sie das Personalbüro an und sagen ihnen, was sie brauchen. Um jemanden einzustellen, müssen Sie eine Menge Dinge wissen - Vorteile, Berechtigungsüberprüfung usw. Aber die Person, die anstellt, muss nichts davon wissen - die Personalagentur kümmert sich um all das.
Auf die gleiche Weise ermöglicht die Verwendung einer Factory dem Konsumenten, neue Objekte zu erstellen, ohne die Details zu kennen, wie sie erstellt wurden oder welche Abhängigkeiten sie haben - er muss nur die Informationen angeben, die er tatsächlich haben möchte.
Höflichkeit
quelle
Das Factory-Muster ist das am häufigsten verwendete und am häufigsten verwendete Entwurfsmuster.
Ich bin auf zahlreiche Fälle gestoßen, in denen eine Factory-Klasse codiert ist, wenn ein einfacher Konstruktor angemessen wäre.
Verwenden Sie keine Werksklasse, es sei denn: -
quelle
Verwenden Sie die Factory-Methode, wenn Sie eine Unterklasse instanziieren und der Client-Code nicht dafür verantwortlich sein soll, zu entscheiden, welche bestimmte Unterklasse instanziiert wird.
Dies ist nützlich, da Sie dadurch den Clientcode nicht ändern müssen, wenn Sie ändern müssen, welche Klasse instanziiert wird. Das Ändern von vorhandenem Code ist eine schlechte Praxis, da er normalerweise fehleranfällig ist.
Ein Beispiel wären Unterklassen, in denen die Daten in aufsteigender Reihenfolge, jedoch auf unterschiedliche Weise sortiert werden. Jeder Weg ist für eine bestimmte Art von Daten optimal. Beispiel: teilweise sortierte Daten, Daten, die Zahlen usw. sind. Der Client-Code ist eine Klasse, die nur das Drucken von Daten verarbeitet. Ein Code, der entscheidet, welche Sortierklasse in der Client-Klasse instanziiert wird, würde sie zu einer komplexen Klasse machen. Mit anderen Worten, Sie haben in diesem Fall mehr als eine Verantwortung, entscheiden, welche Sortierklasse optimal ist, und drucken Daten. Durch Einfügen des Codes, der entscheidet, welche Sortierklasse instanziiert wird, in eine Factory-Klasse werden die Bedenken getrennt, sodass Sie die Client-Klasse nicht jedes Mal ändern müssen, wenn Sie die instanziierte Sortierunterklasse ändern müssen.
Es ist eine Möglichkeit, Ihren Arsch zu bedecken. Wenn Sie voraussehen können, wie oder welche Klasse instanziiert wird, ist die Verwendung von Factory-Klassen sinnvoll. Auf diese Weise können Sie sicherstellen, dass sich Ihre Klassen auf ihre einzige Verantwortung konzentrieren, und es ist weniger wahrscheinlich, dass Sie vorhandenen Code ändern müssen, der nicht in Beziehung steht.
quelle