it-swarm.com.de

Verstößt das Factory-Muster gegen das Open / Closed-Prinzip?

Warum verwendet diese ShapeFactory bedingte Anweisungen, um zu bestimmen, welches Objekt instanziiert werden soll. Müssen wir ShapeFactory nicht ändern, wenn wir in Zukunft weitere Klassen hinzufügen möchten? Warum verstößt dies nicht gegen das Open-Closed-Prinzip?

(Factory Pattern Design

(ShapeFactory Design

14
Armon Safai

Die übliche objektorientierte Weisheit besteht darin, if Anweisungen zu vermeiden und sie durch den dynamischen Versand überschriebener Methoden in Unterklassen einer abstrakten Klasse zu ersetzen. So weit, ist es gut.

Der Punkt des Factory-Musters ist jedoch m Sie davon abzuhalten, die einzelnen Unterklassen zu kennen und nur mit der abstrakten Oberklasse zu arbeiten. Die Idee ist, dass die Factory besser als Sie weiß, welche bestimmte Klasse instanziiert werden soll, und dass Sie besser nur mit den von der Superklasse veröffentlichten Methoden arbeiten sollten. Dies ist oft wahr und ein wertvolles Muster.

Daher kann das Schreiben einer Factory-Klasse auf keinen Fall auf die if -Anweisungen verzichten. Es würde die Last der Auswahl einer bestimmten Klasse auf den Anrufer verlagern, was gena ist, was das Muster vermeiden soll. Nicht alle Prinzipien sind absolut (tatsächlich ist no Prinzip absolut), und wenn Sie dieses Muster verwenden, würden Sie annehmen, dass der Nutzen davon größer ist als der Nutzen, wenn Sie kein if.

20
Kilian Foth

Das Beispiel verwendet wahrscheinlich eine bedingte Anweisung, da dies die einfachste ist. Eine komplexere Implementierung verwendet möglicherweise eine Karte oder Konfiguration oder (wenn Sie wirklich ausgefallen sein möchten) eine Art Registrierung, in der sich die Klassen selbst registrieren können. Es ist jedoch nichts Falsches daran, eine Bedingung zu verwenden, wenn die Anzahl der Klassen gering ist und sich selten ändert.

Die Ausweitung der Bedingung auf die Unterstützung einer neuen Unterklasse in der Zukunft wäre in der Tat streng genommen ein Verstoß gegen das Open/Closed-Prinzip. Die "richtige" Lösung wäre, eine neue Fabrik mit derselben Schnittstelle zu erstellen. Die Einhaltung des O/C-Prinzips sollte jedoch immer gegen andere Designprinzipien wie KISS und YAGNI) abgewogen werden.

Der angezeigte Code ist jedoch eindeutig ein Beispielcode, der das Konzept einer Fabrik und sonst nichts zeigt. Z.B. Es ist wirklich ein schlechter Stil, wie im Beispiel null zurückzugeben, aber eine aufwändigere Fehlerbehandlung würde den Punkt nur verdecken. Beispielcode ist kein Produktionsqualitätscode, den Sie nicht erwarten sollten.

5
JacquesB

Das Muster selbst verstößt nicht gegen das Open/Closed-Prinzip (OCP). Wir verletzen jedoch die OCP, wenn wir das Muster falsch verwenden.

Die einfache Antwort auf diese Frage lautet wie folgt:

  1. Erstellen Sie Ihre Basisfunktionalität mit Factory Method Pattern.
  2. ERWEITERN SIE Ihre Funktionalität mithilfe des Musters Abstract Factory

Im bereitgestellten Beispiel unterstützt Ihre Basisfunktionalität drei Formen: Kreis, Rechteck und Quadrat. Angenommen, Sie müssen in Zukunft Triangle, Pentagon und Hexagon unterstützen. Um dies zu tun OHNE OCP zu verletzen, müssen Sie eine zusätzliche Factory erstellen, um Ihre neuen Formen zu unterstützen (nennen wir AdvancedShapeFactory) und dann - verwenden AbstractFactory, um zu entscheiden, welche Fabrik Sie erstellen müssen, um die gewünschten Formen zu erstellen.

2
hfontanez

Wenn Sie über das Abstract Factory-Muster sprechen, liegt die Entscheidungsfindung häufig nicht in der Factory selbst, sondern im Anwendungscode. Dieser Code wählt aus, welche konkrete Fabrik instanziiert und an den Client-Code weitergegeben werden soll, der die von der Fabrik erzeugten Objekte verwendet. Siehe das Ende des Beispiels Java hier: https://en.wikipedia.org/wiki/Abstract_factory_pattern

Entscheidungsfindung impliziert nicht unbedingt if Anweisungen. Es könnte den konkreten Factory-Typ aus einer Konfigurationsdatei lesen, ihn aus einer Kartenstruktur ableiten usw.

1
guillaume31

Wenn Sie mit dieser Factory über das Öffnen-Schließen auf Klassenebene nachdenken, erstellen Sie eine andere Klasse in Ihrem System zum Öffnen-Schließen. Wenn Sie beispielsweise eine andere Klasse haben, die eine Form annimmt und die Fläche berechnet (typisches Beispiel), ist diese Klasse OpenClose, da Es kann die Fläche für neue Formtypen ohne Änderung berechnen. Dann haben Sie eine andere Klasse, die die Form zeichnet, eine andere Klasse, die N Formen annimmt und die größere zurückgibt, und Sie können allgemein denken, dass die anderen Klassen in Ihrem System, die sich mit Formen befassen, Open-Close sind (zumindest über Formen). Mit Blick auf das Design ermöglicht die Fabrik, dass der Rest des Systems offen und geschlossen ist, und natürlich die Fabrik selbst, die NICHT offen und geschlossen ist.

Natürlich können Sie diese Werkseinstellung auch über eine Art dynamisches Laden öffnen und schließen, und Ihr gesamtes System kann offen-geschlossen sein (Sie können beispielsweise neue Formen hinzufügen, indem Sie ein Glas in den Klassenpfad legen). Sie müssen bewerten, ob sich diese zusätzliche Komplexität je nach dem System, das Sie erstellen, lohnt. Nicht alle Systeme benötigen steckbare Funktionen und nicht alle Systeme müssen vollständig geöffnet und geschlossen sein.

0
AlfredoCasado

Das Open-Closed-Prinzip gilt als Liskov-Substitutionsprinzip für Klassenbäume, für Vererbungshierarchien. In Ihrem Beispiel befindet sich die Factory-Klasse nicht im Stammbaum der Klassen, die sie instanziiert, sodass sie diese Regeln nicht verletzen kann. Es würde eine Verletzung vorliegen, wenn Ihre GetShape (oder besser gesagt CreateShape) in der Shape-Basisklasse implementiert wäre.

0
Martin Maat