Setzt AND (nicht OR oder VS) Builder-Muster

8

Ich habe eine Situation, in der ich ein Builder-Muster zum Konstruieren eines Objekts verwende. Bestes Beispiel ist der Pizza Code

%Vor%

So weit so gut.

Nehmen wir nun einen Anwendungsfall an, in dem ich update the cheese benötige. Das braucht ein setter . Ich habe noch nie ein einziges Beispiel gesehen, bei dem Builder-Muster mit Settern koexistieren, was mich verdächtig macht, dass das, was ich getan habe, ein Anti-Pattern war.

Können Setter UND Builder zusammen existieren?

    
JavaDeveloper 14.03.2014, 21:41
quelle

4 Antworten

11

Sie haben das nie gesehen, weil das Builder-Muster meistens dazu verwendet wird, ein unveränderliches Objekt zu erstellen.

Aber ich verstehe nicht, warum sie nicht nebeneinander existieren konnten. Der Builder erstellt ein Objekt und Sie möchten, dass das erstellte Objekt veränderbar ist. Dann kann es über Setter verfügen. Aber wenn es veränderlich ist und Setter hat, warum sollte man dann das Objekt nicht mit einem einfachen Konstruktor erstellen und die Setter dazu bringen, den Zustand zu ändern? Der Builder ist nicht mehr wirklich nützlich, es sei denn, nur ein oder zwei Felder unter vielen sind veränderbar.

    
JB Nizet 14.03.2014 21:48
quelle
3
  

Nehmen wir nun einen Anwendungsfall an, in dem ich update the cheese benötige. Das benötigt ein setter .

Denken Sie nicht an Setter oder Erbauer , sondern denken Sie an die Verantwortlichkeiten einer Klasse und an die Dienste, die den Benutzern der Klasse zur Verfügung gestellt werden.

Was Sie hier einen Setter nennen, ist einfach ein Service, der ein Objekt transformiert. Ein Builder ist ein Dienst, der ein komplexes Objekt erstellt.

Wenn Sie Settern Zugriff auf Attribute gewähren (oder die Details eines komplexen Objekts, das für den Client geheim bleiben soll), brechen Sie die Kapselung. Das ist ein Anti-Muster. Ihr Käse Beispiel ist nicht ausreichend, um zu enthüllen, warum das schlecht sein könnte. Muss ein Benutzer wissen, dass eine Pizza Käse hat und in der Lage ist, sie zu modifizieren?

Wie JB Nizet sagte, gibt es keinen Grund, warum beide Dienste nicht existieren können, aber Ich würde die Frage stellen, ob das Aufdecken von Details gut ist oder nicht.

    
Fuhrmanator 15.03.2014 17:53
quelle
1

Es ist möglich, dass Sie das Builder-Muster nicht mit Settors gesehen haben, da Ihre Quellen stark an das von GoF veröffentlichte Beispiel gebunden sind. Es kann viele Variationen des Buildermusters geben, und dies gilt für jedes Entwurfsmuster. Das Builder-Muster ist offensichtlich ein schöpferisches Muster, aber die Hauptabsicht des Builder-Musters ist, das Problem von Teleskop-Bauelementen zu lösen. Es ist auch ein gutes Muster, wenn Sie sehr kontrolliert und inkrementell bauen müssen. Keines dieser Dinge, die ich gerade erwähnt habe, wird durch Setter ungültig gemacht. Eine nützliche Variation des Musters besteht darin, über Builder Setter zu haben, die das Vorbereiten des Objektzustands erlauben und dann eine Build-Methode haben, die das Zielobjekt erzeugt / instanziiert. Die Erstellungsmethode erstellt inkrementell das endgültige Objekt und validiert es möglicherweise. Nehmen Sie das folgende Beispiel:

%Vor%

Das obige Beispiel nutzt das Builder-Muster unter Verwendung von Java-Sprachkonstrukten. Es ist tatsächlich ziemlich häufig.

    
kevin 12.02.2015 22:14
quelle
1

Lassen Sie mich noch ein paar Optionen vorschlagen, die weiter in Richtung der ersten Antworten gehen. Wie erwähnt wurde, umfassen die Tugenden des Builder-Musters die Fähigkeit, Wissen über mehrere Schritte hinweg zu akkumulieren, Unterstützung für unveränderliche Instanzen und sicherzustellen, dass ein "frisches" Objekt in einem kohärenten Zustand erzeugt wird. Ich bleibe bei den Konzepten für das Design deiner Frage.

  1. Sie können die Klasse Pizza um eine Instanzmethode erweitern (z. withCheese(boolean value) , die eine neue Pizza -Instanz zurückgibt deren andere Attribute denen der empfangenden Instanz aber entsprechen mit dem angegebenen cheese -Attributwert. Dies bewahrt Unveränderlichkeit des Originals, aber gibt Ihnen eine neue Instanz mit dem beabsichtigter Unterschied.

  2. Sie können die Klasse Pizza um eine Instanzmethode erweitern (z. builder() , das eine Pizza.Builder zurückgibt, initialisiert mit dem Attribute der empfangenden Instanz. Dann alle Methoden schon on Pizza.Builder sind verfügbar, ohne dass eine Instanz hinzugefügt werden muss Methoden je Option 1. Die Kosten dieser Leistung sind die Notwendigkeit, a Endgültiger build() Aufruf am Pizza.Builder .

Also nach der Ausführung

%Vor%

um eine 10-Zoll-Käsepizza zu bekommen, könntest du

ausführen %Vor%

um eine 10-Zoll-Käse-und-Peperoni-Pizza über Option 1 oder

zu bekommen %Vor%

, um dasselbe über Option 2 zu erhalten.

Option 1 ist kürzer, um eine neue Pizza mit einem einzigen Unterschied zu erhalten, erfordert jedoch mehr Aufwand, um alle benötigten Instanzmethoden zu implementieren, und baut mehr Zwischenpizzen, um mehrere Unterschiede zu erzielen.

Option 2 erhält immer Pizza.Builder , nutzt dann aber alle ihre Fähigkeiten, um eine einzelne resultierende Pizza in der gewünschten Konfiguration zu erhalten. Diese Option ermöglicht auch das Hinzufügen weiterer Pizza-Attribute (durch Hinzufügen des Instanzattributs zu Pizza und der einzelnen entsprechenden Methode zu Pizza.Builder .

    
joel.neely 10.11.2016 16:27
quelle

Tags und Links