Was ist der Unterschied zwischen dem Builder-Entwurfsmuster und dem Factory-Entwurfsmuster?
Welche ist vorteilhafter und warum?
Wie stelle ich meine Ergebnisse als Diagramm dar, wenn ich diese Muster testen und vergleichen/gegenüberstellen möchte?
Was ist der Unterschied zwischen dem Builder-Entwurfsmuster und dem Factory-Entwurfsmuster?
Welche ist vorteilhafter und warum?
Wie stelle ich meine Ergebnisse als Diagramm dar, wenn ich diese Muster testen und vergleichen/gegenüberstellen möchte?
Bei Entwurfsmustern gibt es in der Regel keine "vorteilhaftere" Lösung, die in allen Fällen funktioniert. Es kommt darauf an, was Sie implementieren müssen.
Aus Wikipedia:
- Builder konzentriert sich auf den Aufbau einer komplexen Objekts Schritt für Schritt. Abstrakt Factory legt den Schwerpunkt auf eine Familie von Produkt Objekten (entweder einfach oder komplex). Builder gibt das Produkt als endgültiges Schritt zurück, aber in der Abstract Factory, wird das Produkt sofort zurückgegeben.
- Der Bauherr baut oft ein Kompositum.
- Oft werden Entwürfe mit der Factory-Methode begonnen (weniger kompliziert, mehr anpassbar, Unterklassen vermehren sich) und entwickeln sich dann zu Abstract Factory weiter, Prototype, oder Builder (flexibler, komplexer), wenn der Designer entdeckt, wo mehr Flexibilität benötigt wird.
- Manchmal sind schöpferische Muster komplementär: Der Erbauer kann eine der anderen Muster verwenden, um zu implementieren welche Komponenten gebaut werden. Abstrakt Factory, Builder und Prototype können Singleton in ihren Implementierungen verwenden.
Wikipedia-Eintrag zum Factory Design Pattern: http://en.wikipedia.org/wiki/Factory_method_pattern
Wikipedia-Eintrag zum Entwurfsmuster Builder: http://en.wikipedia.org/wiki/Builder_pattern
Das ist genau der Unterschied. Der Builder wird nur benötigt, wenn ein Objekt nicht in einem Schritt erzeugt werden kann. Ein gutes Beispiel dafür ist der De-Serialisierungsprozess eines komplexen Objekts. Oftmals müssen die Parameter für das komplexe Objekt einzeln abgerufen werden.
Zum ersten Satz würde ich sagen, dass es durchaus oft eine vorteilhaftere Lösung gibt, die auf breiter Basis anwendbar ist... wir sehen sie nur nicht, weil sie direkt in die Programmiersprachen eingebettet wird.
@Joel: Ich stimme zu, dass einige Muster verbreiteter sind als andere (zum Beispiel scheint Factory verbreiteter zu sein als Builder), aber was ich meinte, ist, dass keines von ihnen immer besser ist als das andere, egal wie das Szenario aussieht.
Eine Fabrik ist einfach eine Wrapper-Funktion um einen Konstruktor (möglicherweise in einer anderen Klasse). Der Hauptunterschied besteht darin, dass bei einem Fabrikmethodenmuster das gesamte Objekt in einem einzigen Methodenaufruf erstellt werden muss, wobei alle Parameter in einer einzigen Zeile übergeben werden. Das endgültige Objekt wird zurückgegeben.
Ein Baumuster ist dagegen im Wesentlichen ein Wrapper-Objekt, das alle möglichen Parameter umschließt, die Sie an einen Konstruktoraufruf übergeben möchten. So können Sie Setter-Methoden verwenden, um Ihre Parameterliste langsam aufzubauen. Eine zusätzliche Methode einer Builder-Klasse ist eine build()-Methode, die das Builder-Objekt einfach an den gewünschten Konstruktor übergibt und das Ergebnis zurückgibt.
In statischen Sprachen wie Java ist dies besonders wichtig, wenn Sie mehr als eine Handvoll (potenziell optionaler) Parameter haben, da so die Notwendigkeit vermieden wird, Teleskopkonstruktoren für alle möglichen Kombinationen von Parametern zu haben. Mit einem Builder können Sie auch Setter-Methoden verwenden, um schreibgeschützte oder private Felder zu definieren, die nach dem Aufruf des Konstruktors nicht direkt geändert werden können.
Beispiel für eine einfache Fabrik
// Factory
static class FruitFactory {
static Fruit create(name, color, firmness) {
// Additional logic
return new Fruit(name, color, firmness);
}
}
// Usage
Fruit fruit = FruitFactory.create("apple", "red", "crunchy");
Beispiel für einen Basic Builder
// Builder
class FruitBuilder {
String name, color, firmness;
FruitBuilder setName(name) { this.name = name; return this; }
FruitBuilder setColor(color) { this.color = color; return this; }
FruitBuilder setFirmness(firmness) { this.firmness = firmness; return this; }
Fruit build() {
return new Fruit(this); // Pass in the builder
}
}
// Usage
Fruit fruit = new FruitBuilder()
.setName("apple")
.setColor("red")
.setFirmness("crunchy")
.build();
Es könnte sich lohnen, die Codebeispiele auf diesen beiden Wikipedia-Seiten zu vergleichen:
http://en.wikipedia.org/wiki/Factory_method_pattern
http://en.wikipedia.org/wiki/Builder_pattern
Das ist nicht die korrekte Verwendung von Builder-Muster imo, auch in der Wiki-Link, den Sie pased Verwendung ist anders. Dieser FruitBuilder ist eine Mischung aus Director- und Builder-Komponente, bei der man build() aufruft, die zum Director gehören sollte, und Setter, die zur Builder-Komponente gehören. Der Director sollte die Geschäftslogik enthalten, wie ein Objekt mit den Builder-Methoden zu erstellen ist. Fluent apis sind keine Builder-Muster und StringBuilder ist auch kein Builder-Muster.
Es gibt zwei verschiedene Muster, die gemeinhin als "Builder" bezeichnet werden: a) Erbauer nach "Design Patterns: Elemente wiederverwendbarer objektorientierter Software" von Erich Gamma Richard Helm, Ralph Johnson und John Vlissides --- b) Ersteller nach "Effective Java", von Joshua Bloch . "Betrachten Sie einen Builder, wenn Sie mit vielen Konstruktorparametern konfrontiert werden." Dieses Muster verwendet Methodenkaskadierung / flüssige Schnittstelle um (unveränderliche) Objekte mit einer Vielzahl von Attributen zu initialisieren.
Das Factory-Muster kann fast als eine vereinfachte Version des Builder-Musters angesehen werden.
In der Fabrik Muster ist die Fabrik für die Erstellung verschiedener Untertypen eines Objekts je nach Bedarf zuständig.
Der Benutzer einer Fabrikmethode braucht den genauen Subtyp des Objekts nicht zu kennen. Ein Beispiel für eine Fabrikmethode createCar
könnte eine Ford
oder eine Honda
typisiertes Objekt.
In der Bauherr Muster werden verschiedene Untertypen ebenfalls durch eine Builder-Methode erstellt, aber die Zusammensetzung der Objekte kann innerhalb derselben Unterklasse unterschiedlich sein.
Um das Beispiel mit dem Auto fortzusetzen, könnten Sie ein createCar
Builder-Methode, die eine Honda
-artiges Objekt mit einem 4-Zylinder-Motor, oder ein Honda
-typisiertes Objekt mit 6 Zylindern. Das Builder-Muster ermöglicht diese feinere Granularität.
Diagramme der beiden Bauherren-Muster und die Muster der Fabrikmethode sind auf Wikipedia verfügbar.
Das Builder Design Pattern beschreibt ein Objekt, das weiß, wie man ein anderes Objekt eines bestimmten Typs über mehrere Schritte herstellt. Bei jedem Zwischenschritt hält es den erforderlichen Zustand für das Zielobjekt fest. Stellen Sie sich vor, was der StringBuilder durchläuft, um eine endgültige Zeichenkette zu erzeugen.
Das Factory Design Pattern beschreibt ein Objekt, das mehrere verschiedene, aber verwandte Arten von Objekten in einem Schritt erstellen kann, wobei der spezifische Typ auf der Grundlage gegebener Parameter ausgewählt wird. Denken Sie an das Serialisierungssystem, bei dem Sie Ihren Serialisierer erstellen und dieser das gewünschte Objekt in einem einzigen Ladeaufruf konstruiert.
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.
14 Stimmen
Da sie unterschiedliche Dinge tun, was meinen Sie mit "vorteilhaft"?
8 Stimmen
Bauherr ist eine komplexere Version von Konstrukteur - während Fabrikmethode ist eine vereinfachte Version.
0 Stimmen
@DávidHorváth Ich würde einen Builder nicht als "komplexer" bezeichnen. Wenn man es mit einem Konstruktor zu tun hat, der 100 Parameter hat, und man sich nur für 3 davon interessiert, und man weiß, dass sich die Anzahl der Parameter in der Zukunft ändern könnte, würde die Verwendung des Builder-Musters das Leben aller Beteiligten sehr viel einfacher machen.
2 Stimmen
@Aberrant Komplizierte Nutzung und architektonische Komplexität sind zwei verschiedene Dinge. Ich habe mich auf Letzteres konzentriert.