Was ist der Unterschied zwischen dem Builder-Entwurfsmuster und dem Factory-Entwurfsmuster?
Welches ist vorteilhafter und warum?
Wie stelle ich meine Ergebnisse als Grafik dar, wenn ich diese Muster testen und vergleichen / kontrastieren möchte?
Was ist der Unterschied zwischen dem Builder-Entwurfsmuster und dem Factory-Entwurfsmuster?
Welches ist vorteilhafter und warum?
Wie stelle ich meine Ergebnisse als Grafik dar, wenn ich diese Muster testen und vergleichen / kontrastieren möchte?
Antworten:
Bei Entwurfsmustern gibt es normalerweise keine "vorteilhaftere" Lösung, die für alle Fälle funktioniert. Dies hängt davon ab, was Sie implementieren müssen.
Aus Wikipedia:
- Builder konzentriert sich darauf, Schritt für Schritt ein komplexes Objekt zu erstellen. Abstract Factory betont eine Familie von Produktobjekten (entweder einfach oder komplex). Builder gibt das Produkt als letzten Schritt zurück, aber in Bezug auf die Abstract Factory wird das Produkt sofort zurückgegeben.
- Builder erstellt häufig ein Composite.
- Entwürfe beginnen häufig mit der Factory-Methode (weniger kompliziert, anpassbarer, Unterklassen vermehren sich) und entwickeln sich zu Abstract Factory, Prototype oder Builder (flexibler, komplexer), wenn der Designer feststellt, wo mehr Flexibilität erforderlich ist.
- Manchmal ergänzen sich Kreationsmuster: Builder kann eines der anderen Muster verwenden, um zu implementieren, welche Komponenten erstellt werden. Abstract Factory, Builder und Prototype können Singleton in ihren Implementierungen verwenden.
Wikipedia-Eintrag für das Factory-Design-Muster: http://en.wikipedia.org/wiki/Factory_method_pattern
Wikipedia-Eintrag für das Builder-Entwurfsmuster: http://en.wikipedia.org/wiki/Builder_pattern
Eine Factory ist einfach eine Wrapper-Funktion um einen Konstruktor (möglicherweise eine in einer anderen Klasse). Der Hauptunterschied besteht darin, dass für ein Factory-Methodenmuster 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 Builder-Muster ist im Wesentlichen ein Wrapper-Objekt um alle möglichen Parameter, die Sie möglicherweise an einen Konstruktoraufruf übergeben möchten. Auf diese Weise können Sie Setter-Methoden verwenden, um Ihre Parameterliste langsam aufzubauen. Eine zusätzliche Methode für eine 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 wird dies wichtiger, wenn Sie über mehr als eine Handvoll (möglicherweise optionaler) Parameter verfügen, da keine Teleskopkonstruktoren für alle möglichen Kombinationen von Parametern erforderlich sind. 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.
Grundlegendes Fabrikbeispiel
// 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 einfachen 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 kann sich lohnen, die Codebeispiele dieser beiden Wikipedia-Seiten zu vergleichen:
http://en.wikipedia.org/wiki/Factory_method_pattern
http://en.wikipedia.org/wiki/Builder_pattern
Das Factory-Muster kann fast als vereinfachte Version des Builder-Musters angesehen werden.
In der Fabrik Muster ist die Factory dafür verantwortlich, je nach Bedarf verschiedene Untertypen eines Objekts zu erstellen.
Der Benutzer einer Factory-Methode muss den genauen Subtyp dieses Objekts nicht kennen. Ein Beispiel für eine Factory-Methode createCar
könnte a Ford
oder a zurückgebenHonda
typisiertes Objekt zurückgeben.
Im Builder- Muster werden auch verschiedene Untertypen von einer Builder-Methode erstellt, die Zusammensetzung der Objekte kann jedoch innerhalb derselben Unterklasse unterschiedlich sein.
Um das Auto-Beispiel fortzusetzen, haben Sie möglicherweise eine createCar
Builder-Methode, die ein Honda
Objekt vom Typ mit einem 4-Zylinder-Motor erstellt, oder aHonda
Objekt vom Typ mit 6 Zylindern erstellt. Das Builder-Muster ermöglicht diese feinere Granularität.
Diagramme sowohl des Builder-Musters als auch des Factory-Methodenmusters sind auf Wikipedia verfügbar.
Das Builder-Entwurfsmuster beschreibt ein Objekt, das in mehreren Schritten ein anderes Objekt eines bestimmten Typs erstellen kann. Es enthält den erforderlichen Status für das Zielobjekt bei jedem Zwischenschritt. Überlegen Sie, was StringBuilder durchläuft, um eine endgültige Zeichenfolge zu erstellen.
Das Factory-Entwurfsmuster beschreibt ein Objekt, das in einem Schritt mehrere verschiedene, aber verwandte Objekttypen erstellen kann, wobei der spezifische Typ anhand der angegebenen Parameter ausgewählt wird. Stellen Sie sich das Serialisierungssystem vor, in dem Sie Ihren Serializer erstellen und das gewünschte Objekt in einem einzigen Ladeaufruf erstellen.
Schritt für Schritt ein komplexes Objekt erstellen: Builder-Muster
Ein einfaches Objekt wird mit einer einzigen Methode erstellt: dem Factory-Methodenmuster
Erstellen eines Objekts mithilfe mehrerer Factory-Methoden: Abstraktes Factory-Muster
Builder Pattern und Factory Pattern scheinen beide bloßen Augen ziemlich ähnlich zu sein, da sie beide Objekte für Sie erstellen.
Dieses Beispiel aus dem wirklichen Leben wird den Unterschied zwischen den beiden deutlicher machen.
Angenommen, Sie ging zu einem Fast - Food - Restaurant und bestellten Essen .
Pizza
Capsicum, Tomate, BBQ Huhn, keine Ananas
So werden verschiedene Arten von Lebensmitteln nach dem Factory-Muster hergestellt, aber die verschiedenen Varianten (Aromen) eines bestimmten Lebensmittels werden nach dem Builder-Muster hergestellt.
Verschiedene Arten von Lebensmitteln
Pizza, Burger, Pasta
Varianten der Pizza
Nur Käse, Käse + Tomaten + Paprika, Käse + Tomaten usw.
Sie können die Beispielcode-Implementierung beider Muster hier sehen.
Builder Pattern
Factory Pattern
Beide sind Schöpfungsmuster, um ein Objekt zu erstellen.
1) Factory Pattern - Angenommen, Sie haben eine Superklasse und N Unterklassen. Das erstellte Objekt hängt davon ab, welcher Parameter / Wert übergeben wird.
2) Builder-Muster - um ein komplexes Objekt zu erstellen.
Ex: Make a Loan Object. Loan could be house loan, car loan ,
education loan ..etc. Each loan will have different interest rate, amount ,
duration ...etc. Finally a complex object created through step by step process.
Zunächst einige allgemeine Dinge, die meiner Argumentation folgen sollen:
Die größte Herausforderung beim Entwurf großer Softwaresysteme besteht darin, dass sie flexibel und unkompliziert sein müssen, um Änderungen vorzunehmen. Aus diesem Grund gibt es einige Metriken wie Kopplung und Kohäsion. Um Systeme zu erhalten, deren Funktionalität leicht geändert oder erweitert werden kann, ohne dass das gesamte System von Grund auf neu entworfen werden muss, können Sie den Entwurfsprinzipien (wie SOLID usw.) folgen. Nach einer Weile erkannten einige Entwickler, dass es ähnliche Lösungen gibt, die bei ähnlichen Problemen gut funktionieren, wenn sie diesen Prinzipien folgen. Diese Standardlösungen erwiesen sich als Entwurfsmuster.
Die Entwurfsmuster sollen Sie also dabei unterstützen, die allgemeinen Entwurfsprinzipien zu befolgen, um lose gekoppelte Systeme mit hoher Kohäsion zu erzielen.
Beantwortung der Frage:
Wenn Sie nach dem Unterschied zwischen zwei Mustern fragen, müssen Sie sich fragen, welches Muster Ihr System auf welche Weise flexibler macht. Jedes Muster hat seinen eigenen Zweck, Abhängigkeiten zwischen Klassen in Ihrem System zu organisieren.
Das abstrakte Factory-Muster: GoF: „Stellen Sie eine Schnittstelle zum Erstellen von Familien verwandter oder abhängiger Objekte bereit, ohne deren konkrete Klassen anzugeben.“
Was bedeutet das? Durch die Bereitstellung einer solchen Schnittstelle wird der Aufruf des Konstruktors für jedes Produkt der Familie in der Factory-Klasse gekapselt. Und da dies der einzige Ort in Ihrem gesamten System ist, an dem diese Konstruktoren aufgerufen werden, können Sie Ihr System ändern, indem Sie eine neue Factory-Klasse implementieren. Wenn Sie die Darstellung der Fabrik durch eine andere austauschen, können Sie eine ganze Reihe von Produkten austauschen, ohne den größten Teil Ihres Codes zu berühren.
Das Builder-Muster: GoF: „Trennen Sie die Konstruktion eines komplexen Objekts von seiner Darstellung, damit derselbe Konstruktionsprozess unterschiedliche Darstellungen erstellen kann.“
Was bedeutet das ? Sie kapseln den Konstruktionsprozess in einer anderen Klasse, dem Director (GoF). Dieser Director enthält den Algorithmus zum Erstellen neuer Instanzen des Produkts (z. B. Erstellen eines komplexen Produkts aus anderen Teilen). Um die integralen Bestandteile des gesamten Produkts zu erstellen, verwendet der Director einen Builder. Durch Austauschen des Builders im Director können Sie denselben Algorithmus zum Erstellen des Produkts verwenden, jedoch die Darstellungen einzelner Teile (und damit die Darstellung des Produkts) ändern. Um Ihr System in der Darstellung des Produkts zu erweitern oder zu ändern, müssen Sie lediglich eine neue Builder-Klasse implementieren.
Kurz gesagt: Der Zweck des Abstract Factory Patterns besteht darin, eine Reihe von Produkten auszutauschen, die für die gemeinsame Verwendung hergestellt wurden. Das Builder-Muster dient dazu, den abstrakten Algorithmus zum Erstellen eines Produkts zu kapseln, um es für verschiedene Darstellungen des Produkts wiederzuverwenden.
Meiner Meinung nach kann man nicht sagen, dass das Abstract Factory Pattern der große Bruder des Builder Pattern ist. JA, beide sind Schöpfungsmuster, aber die Hauptabsicht der Muster ist völlig unterschiedlich.
Ein bemerkenswerter Unterschied zwischen Baumeister und Fabrik, den ich erkennen konnte, war der folgende
Angenommen, wir haben ein Auto
class Car
{
bool HasGPS;
bool IsCityCar;
bool IsSportsCar;
int Cylenders;
int Seats;
public:
void Car(bool hasGPs=false,bool IsCityCar=false,bool IsSportsCar=false, int Cylender=2, int Seats=4);
};
In der obigen Oberfläche können wir Auto auf folgende Weise bekommen:
int main()
{
BadCar = new Car(false,false,true,4,4);
}
aber was ist, wenn beim Erstellen der Sitze eine Ausnahme auftritt? SIE ERHALTEN DAS OBJEKT NICHT // ABER
Angenommen, Sie haben eine Implementierung wie die folgende
class Car
{
bool mHasGPS;
bool mIsCityCar;
bool mIsSportsCar;
int mCylenders;
int mSeats;
public:
void Car() : mHasGPs(false), mIsCityCar(false), mIsSportsCar(false), mCylender(2), mSeats(4) {}
void SetGPS(bool hasGPs=false) {mHasGPs = hasGPs;}
void SetCity(bool CityCar) {mIsCityCar = CityCar;}
void SetSports(bool SportsCar) {mIsSportsCar = SportsCar;}
void SetCylender(int Cylender) {mCylenders = Cylender;}
void SetSeats(int seat) {mSeats = seat;}
};
class CarBuilder
{
Car* mCar;
public:
CarBuilder():mCar(NULL) { mCar* = new Car(); }
~CarBuilder() { if(mCar) { delete mCar; }
Car* GetCar() { return mCar; mCar=new Car(); }
CarBuilder* SetSeats(int n) { mCar->SetSeats(n); return this; }
CarBuilder* SetCylender(int n) { mCar->SetCylender(n); return this; }
CarBuilder* SetSports(bool val) { mCar->SetSports(val); return this; }
CarBuilder* SetCity(bool val) { mCar->SetCity(val); return this; }
CarBuilder* SetGPS(bool val) { mCar->SetGPS(val); return this; }
}
Jetzt können Sie so erstellen
int main()
{
CarBuilder* bp =new CarBuilder;
Car* NewCar = bp->SetSeats(4)->SetSports(4)->SetCity(ture)->SetGPS(false)->SetSports(true)->GetCar();
bp->SetSeats(2);
bp->SetSports(4);
bp->SetCity(ture);
bp->SetSports(true)
Car* Car_II= bp->GetCar();
}
Hier im zweiten Fall würden Sie das Auto auch dann erhalten, wenn eine Operation fehlschlägt.
Vielleicht funktioniert das Auto später nicht mehr perfekt, aber Sie hätten das Objekt.
Weil die Factory-Methode Ihnen das Auto in einem einzigen Anruf gibt, während der Builder eins nach dem anderen baut.
Obwohl es von den Bedürfnissen des Deign abhängt, für wen man sich entscheidet.
+-------------------------------------------------------------------+---------------------------------------------------+
| Builder | Factory |
+-------------------------------------------------------------------+---------------------------------------------------+
| Return only single instance to handle complex object construction | Retrun various instances on multiple constructors |
| No interface required | Interface driven |
| Inner classes is involved (to avoid telescopic constructors) | Subclasses are involved |
+-------------------------------------------------------------------+---------------------------------------------------+
Analogie:
Builder und Abstract Factory haben für unterschiedliche Zwecke gedacht. Je nach richtigem Anwendungsfall müssen Sie ein geeignetes Entwurfsmuster auswählen.
Hauptmerkmale des Builders :
Fabrik (einfache Fabrik) herausragende Merkmale:
Entwürfe beginnen häufig mit der Factory-Methode (weniger kompliziert, anpassbarer, Unterklassen vermehren sich) und entwickeln sich zu Abstract Factory , Prototype oder Builder (flexibler, komplexer).
Schauen Sie sich verwandte Beiträge an:
Builder in einer separaten Klasse halten (fließende Schnittstelle)
Entwurfsmuster: Factory vs Factory-Methode vs Abstract Factory
Weitere Informationen finden Sie in den folgenden Artikeln:
Factory : Wird zum Erstellen einer Instanz eines Objekts verwendet, bei der die Abhängigkeiten des Objekts vollständig von der Factory gehalten werden. Für das abstrakte Fabrikmuster gibt es oft viele konkrete Implementierungen derselben abstrakten Fabrik. Die richtige Implementierung der Fabrik erfolgt über die Abhängigkeitsinjektion.
Builder : Wird zum Erstellen unveränderlicher Objekte verwendet, wenn die Abhängigkeiten des zu instanziierenden Objekts teilweise im Voraus bekannt sind und teilweise vom Client des Builders bereitgestellt werden.
Abstrakte Factory & Builder-Muster sind beide Schöpfungsmuster, jedoch mit unterschiedlicher Absicht.
Das abstrakte Fabrikmuster betont die Objekterstellung für Familien verwandter Objekte, wobei:
Das Builder-Muster konzentriert sich darauf, Schritt für Schritt ein komplexes Objekt zu erstellen. Es entkoppelt die Darstellung vom Konstruktionsprozess des komplexen Objekts, sodass derselbe Konstruktionsprozess für verschiedene Repräsentationen verwendet werden kann.
Eine komplexe Konstruktion liegt vor, wenn das zu konstruierende Objekt aus verschiedenen anderen Objekten besteht, die durch Abstraktionen dargestellt werden.
Betrachten Sie ein Menü in McDonald's. Ein Menü enthält ein Getränk, ein Hauptgericht und eine Seite. Abhängig davon, welche Nachkommen der einzelnen Abstraktionen zusammengesetzt sind, hat das erstellte Menü eine andere Darstellung.
Dort haben wir zwei Instanzen des Menüs mit unterschiedlichen Darstellungen. Der Bauprozess bleibt wiederum der gleiche. Sie erstellen ein Menü mit einem Getränk, einem Hauptgericht und einer Beilage.
Mithilfe des Builder-Musters trennen Sie den Algorithmus zum Erstellen eines komplexen Objekts von den verschiedenen Komponenten, mit denen es erstellt wurde.
In Bezug auf das Builder-Muster ist der Algorithmus im Director gekapselt, während die Builder zum Erstellen der Integralteile verwendet werden. Das Variieren des verwendeten Builders im Algorithmus des Direktors führt zu einer anderen Darstellung, da andere Teile zu einem Menü zusammengesetzt sind. Die Art und Weise, wie ein Menü erstellt wird, bleibt gleich.
Der Hauptunterschied zwischen ihnen besteht darin, dass das Builder-Muster in erster Linie die schrittweise Erstellung komplexer Objekte beschreibt. Im Muster der abstrakten Fabrik liegt der Schwerpunkt auf Familien von Objektprodukten . Builder gibt das Produkt im letzten Schritt zurück . Im Abstract Factory-Muster ist das Produkt sofort verfügbar .
Beispiel: Nehmen wir an, wir erstellen Maze
1. Abstrakte Fabrik:
Maze* MazeGame::CreateMaze (MazeFactory& factory) {
Maze* maze = factory.MakeMaze(); /// product is available at start!!
/* Call some methods on maze */
return maze;
}
2. Erbauer:
Maze* MazeGame::CreateMaze (MazeBuilder& builder) {
builder.buildMaze(); /// We don't have access to maze
/* Call some methods on builder */
return builder.GetMaze();
}
Ich glaube, die Verwendung und der Unterschied zwischen Factory & Builder-Mustern können in einem bestimmten Zeitraum leichter verstanden / geklärt werden, da Sie an derselben Codebasis gearbeitet haben und sich die Anforderungen geändert haben.
Nach meiner Erfahrung beginnen Sie normalerweise mit einem Factory-Muster, das einige statische Erstellungsmethoden enthält, um in erster Linie eine relativ komplexe Initialisierungslogik zu verbergen. Wenn Ihre Objekthierarchie komplexer wird (oder wenn Sie mehr Typen und Parameter hinzufügen), werden Ihre Methoden wahrscheinlich mit mehr Parametern gefüllt, und ganz zu schweigen davon, dass Sie Ihr Factory-Modul neu kompilieren müssen. All diese Dinge erhöhen die Komplexität Ihrer Erstellungsmethoden, verringern die Lesbarkeit und machen das Erstellungsmodul anfälliger.
Dieser Punkt ist möglicherweise der Übergangs- / Erweiterungspunkt. Auf diese Weise erstellen Sie ein Wrapper-Modul um die Konstruktionsparameter und können dann neue (ähnliche) Objekte darstellen, indem Sie (möglicherweise) weitere Abstraktionen und Implementierungen hinzufügen, ohne die tatsächliche Erstellungslogik zu berühren. Sie hatten also "weniger" komplexe Logik.
Ehrlich gesagt ist es der Unterschied, sich auf etwas zu beziehen, bei dem "ein Objekt in einem oder mehreren Schritten erstellt wird", da der einzige Diversitätsfaktor für mich nicht ausreichte, um sie zu unterscheiden, da ich in fast allen Fällen, mit denen ich konfrontiert war, beide Methoden verwenden konnte jetzt ohne irgendeinen Nutzen zu erfahren. Das ist es also, worüber ich endlich nachgedacht habe.
Der Hauptvorteil des Builder-Musters gegenüber dem Factory-Muster besteht darin, dass Sie ein Standardobjekt mit vielen möglichen Anpassungen erstellen möchten, in der Regel jedoch nur wenige anpassen.
Wenn Sie beispielsweise einen HTTP-Client schreiben möchten, richten Sie einige Standardparameter wie Standard-Schreib- / Lesezeitlimit, Protokolle, Cache, DNS, Interceptors usw. ein.
Die meisten Benutzer Ihres Clients verwenden nur diese Standardparameter, während einige andere Benutzer möglicherweise einige der anderen Parameter anpassen möchten. In einigen Fällen möchten Sie nur die Zeitüberschreitungen ändern und den Rest unverändert verwenden. In anderen Fällen müssen Sie möglicherweise beispielsweise den Cache anpassen.
Es gibt folgende Möglichkeiten, Ihren Client zu instanziieren (aus OkHttpClient):
//just give me the default stuff
HttpClient.Builder().build()
//I want to use custom cache
HttpClient.Builder().cache(MyCache()).build()
//I want custom connection timeout
HttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS).build()
//I am more interested in read/write timeout
HttpClient.Builder()
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS).build()
Wenn Sie hierfür ein Factory-Muster verwenden, werden Sie am Ende viele Methoden mit allen möglichen Kombinationen von Erstellungsparametern schreiben. Mit dem Builder geben Sie einfach diejenigen an, die Sie interessieren, und lassen den Builder sie für Sie erstellen, wobei Sie sich um all diese anderen Parameter kümmern.
Das Erstellungsmuster betont die Komplexität des Erstellens eines Objekts (gelöst durch "Schritte").
Das abstrakte Muster betont "nur" die "Abstraktion" von (mehreren, aber verwandten) Objekten.
Der Unterschied ist klar. Im Builder-Muster erstellt der Builder einen bestimmten Objekttyp für Sie. Sie müssen sagen, was der Builder bauen muss. Im Factory-Muster erstellen Sie mit der abstrakten Klasse direkt das spezifische Objekt.
Hier fungiert die Builder-Klasse als Vermittler zwischen der Hauptklasse und bestimmten Typklassen. Mehr Abstraktion.
Beide sind sich sehr ähnlich. Wenn Sie jedoch eine große Anzahl von Parametern für die Objekterstellung haben, von denen einige optional sind und einige Standardwerte aufweisen, wählen Sie das Builder-Muster.
meiner bescheidenen Meinung nach
Builder ist eine Art komplexere Fabrik.
Aber in Builder können Sie Objekte instanziiert mit anderen Fabriken verwenden , die erforderlich sind , endgültig und gültiges Objekt zu bauen.
Wenn Sie also über die Entwicklung von "Schöpfungsmustern" nach Komplexität sprechen, können Sie folgendermaßen darüber nachdenken:
Dependency Injection Container -> Service Locator -> Builder -> Factory
Beide Muster haben die gleiche Notwendigkeit: Verstecken Sie die Konstruktionslogik eines komplexen Objekts vor einem Client-Code. Aber was macht "komplex" (oder manchmal kompliziert) ein Objekt? Hauptsächlich liegt es an Abhängigkeiten oder vielmehr am Zustand eines Objekts, das aus mehr Teilzuständen besteht. Sie können Abhängigkeiten nach Konstruktor einfügen, um den anfänglichen Objektstatus festzulegen. Für ein Objekt sind jedoch möglicherweise viele erforderlich. Einige befinden sich in einem anfänglichen Standardzustand (nur weil wir hätten lernen müssen, dass das Festlegen einer Standardabhängigkeit auf null nicht der sauberste Weg ist ) und eine andere Einstellung in einen Zustand, der von einer bestimmten Bedingung bestimmt wird. Darüber hinaus gibt es Objekteigenschaften, die eine Art "ahnungslose Abhängigkeiten" darstellen, aber auch optionale Zustände annehmen können.
Es gibt zwei bekannte Möglichkeiten, diese Komplexität zu beherrschen:
Zusammensetzung / Aggregation: Konstruieren Sie ein Objekt, konstruieren Sie seine abhängigen Objekte und verbinden Sie es dann. Hier kann ein Builder den Prozess, der die Regeln für die Konstruktion von Komponenten festlegt, transparent und flexibel gestalten.
Polymorphismus: Konstruktionsregeln werden direkt in der Subtypdefinition deklariert, sodass Sie für jeden Subtyp eine Reihe von Regeln haben und eine Bedingung entscheidet, welche dieser Regeln für die Konstruktion des Objekts gelten. Eine Fabrik passt perfekt in dieses Szenario.
Nichts hindert daran, diese beiden Ansätze zu vermischen. Eine Produktfamilie kann die mit einem Builder erstellte Objekterstellung abstrahieren. Ein Builder kann mithilfe von Fabriken bestimmen, welches Komponentenobjekt instanziiert wird.
Meiner Meinung nach wird das Builder-Muster verwendet, wenn Sie ein Objekt aus einer Reihe anderer Objekte erstellen möchten und die Erstellung eines Teils unabhängig von dem Objekt sein muss, das Sie erstellen möchten. Es ist hilfreich, die Erstellung von Teilen vor dem Client zu verbergen, um Builder und Client unabhängig zu machen. Es wird für die Erstellung komplexer Objekte verwendet (Objekte, die aus komplizierten Eigenschaften bestehen können).
Während das Factory-Muster angibt, dass Sie Objekte einer gemeinsamen Familie erstellen möchten und diese sofort bearbeitet werden sollen. Es wird für einfachere Objekte verwendet.
Baumeister und abstrakte Fabrik
Das Builder-Entwurfsmuster ist dem Abstract Factory-Muster in gewissem Maße sehr ähnlich. Deshalb ist es wichtig, in der Lage zu sein, den Unterschied zwischen den Situationen zu unterscheiden, in denen die eine oder andere verwendet wird. Im Fall der Abstract Factory verwendet der Client die Methoden der Factory, um eigene Objekte zu erstellen. Im Fall des Builders wird die Builder-Klasse angewiesen, wie das Objekt erstellt wird, und dann wird sie danach gefragt. Die Art und Weise, wie die Klasse zusammengesetzt wird, hängt jedoch von der Builder-Klasse ab. Dieses Detail macht den Unterschied zwischen den beiden Mustern aus.
Gemeinsame Schnittstelle für Produkte
In der Praxis haben die von den Betonbauern erstellten Produkte eine erheblich andere Struktur. Wenn es also keinen Grund gibt, unterschiedliche Produkte abzuleiten, wird eine gemeinsame Elternklasse verwendet. Dies unterscheidet auch das Builder-Muster vom Abstract Factory-Muster, mit dem Objekte erstellt werden, die von einem gemeinsamen Typ abgeleitet sind.
Das Factory-Muster erstellt zur Laufzeit eine konkrete Implementierung einer Klasse, dh die Hauptabsicht besteht darin, mithilfe des Polymorphismus zu entscheiden, welche Klasse instanziiert werden soll. Dies bedeutet, dass wir zur Kompilierungszeit nicht genau wissen, welche Klasse erstellt wird, während sich das Builder-Muster hauptsächlich mit der Lösung des Problems des Antipatterns von Teleskopkonstruktoren befasst, das aufgrund einer großen Anzahl optionaler Felder einer Klasse auftritt. Im Builder-Muster gibt es keine Vorstellung von Polymorphismus, da wir wissen, welches Objekt wir zur Kompilierungszeit konstruieren möchten.
Das einzige gemeinsame Thema dieser beiden Muster ist das Ausblenden von Konstruktoren und die Objekterstellung hinter Factory-Methoden sowie die Build-Methode für eine verbesserte Objektkonstruktion.
Mit dem Factory-Muster können Sie ein Objekt sofort erstellen, während Sie mit dem Builder-Muster den Erstellungsprozess eines Objekts unterbrechen können. Auf diese Weise können Sie beim Erstellen eines Objekts verschiedene Funktionen hinzufügen.