Was ist der Unterschied zwischen Builder Design Pattern und Factory Design Pattern?

Was ist der Unterschied zwischen dem Builder-Entwurfsmuster und dem Factory-Entwurfsmuster?

Welcher ist vorteilhafter und warum?

Wie stelle ich meine Ergebnisse als Diagramm dar, wenn ich diese Muster testen und vergleichen / kontrastieren möchte?

    Bei Entwurfsmustern gibt es normalerweise keine “vorteilhaftere” Lösung, die für alle Fälle funktioniert. Es hängt davon ab, was Sie implementieren müssen.

    Aus Wikipedia:

    • Builder konzentriert sich darauf, ein komplexes Objekt Schritt für Schritt aufzubauen. Abstract Factory betont eine Familie von Produktobjekten (entweder einfach oder komplex). Der Builder gibt das Produkt als letzten Schritt zurück, aber für die Abstract Factory wird das Produkt sofort zurückgegeben.
    • Der Builder erstellt häufig einen Verbund.
    • Oft beginnen Designs mit der Factory-Methode (weniger kompliziert, besser anpassbar, Unterklassen) und entwickeln sich zu Abstract Factory, Prototype oder Builder (flexibler, komplexer), wenn der Designer erkennt, wo mehr Flexibilität benötigt wird.
    • Manchmal ergänzen sich kreative Muster: 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 Factory-Design-Muster: http://en.wikipedia.org/wiki/Factory_method_pattern

    Wikipedia-Eintrag für Builder-Entwurfsmuster: http://en.wikipedia.org/wiki/Builder_pattern

    Das Factory-Muster kann fast als eine vereinfachte Version des Builder-Musters angesehen werden.

    Im Factory- Muster ist die Factory für die Erstellung verschiedener Subtypen eines Objekts abhängig von den Anforderungen verantwortlich.

    Der Benutzer einer Factory-Methode muss den genauen Untertyp des Objekts nicht kennen. Ein Beispiel für eine Factory-Methode createCar könnte ein Ford oder Honda typisiertes Objekt zurückgeben.

    Im Builder- Muster werden auch verschiedene Subtypen durch eine Builder-Methode erstellt, aber die Zusammensetzung der Objekte kann innerhalb derselben Unterklasse abweichen.

    Um das Auto-Beispiel fortzusetzen, haben Sie vielleicht eine createCar Builder-Methode, die ein Honda Typ-Objekt mit einem 4-Zylinder-Motor oder ein Honda Typ-Objekt mit 6 Zylindern erzeugt. Das Builder-Muster ermöglicht diese feinere Granularität.

    Diagramme des Builder-Musters und des Factory-Verfahrensmusters sind auf Wikipedia verfügbar.

    Eine Factory ist einfach eine Wrapper-function um einen Konstruktor (möglicherweise einer in einer anderen class). Der Hauptunterschied besteht darin, dass ein Fabrikmethodenmuster das gesamte Objekt in einem einzigen Methodenaufruf erstellen muss, wobei alle Parameter in einer einzelnen Zeile übergeben werden. Das endgültige Objekt wird zurückgegeben.

    Ein Builder-Muster hingegen ist im Wesentlichen ein Wrapper-Objekt um alle möglichen Parameter herum, 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 weitere Methode für eine Builder-class 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 mehr als eine Handvoll (potenziell optionaler) Parameter haben, da es die Anforderung vermeidet, teleskopische Konstruktoren für alle möglichen Kombinationen von Parametern zu haben. Ein Builder ermöglicht Ihnen außerdem, mithilfe von Setter-Methoden schreibgeschützte oder private Felder zu definieren, die nicht direkt geändert werden können, nachdem der Konstruktor aufgerufen wurde.

    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"); 

    Einfaches Builder-Beispiel

     // 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 lohnt sich vielleicht, die Codebeispiele aus diesen zwei Wikipedia-Seiten zu vergleichen:

    http://en.wikipedia.org/wiki/Factory_method_pattern
    http://en.wikipedia.org/wiki/Builder_pattern

    Das Builder-Entwurfsmuster beschreibt ein Objekt, das weiß, wie ein anderes Objekt eines bestimmten Typs in mehreren Schritten erstellt wird. Es enthält den erforderlichen Status für den Zielartikel in jedem Zwischenschritt. Überlegen Sie, was StringBuilder durchläuft, um eine endgültige Zeichenfolge zu erzeugen.

    Das Factory-Design-Muster beschreibt ein Objekt, das weiß, wie mehrere verschiedene, aber verwandte Objekttypen in einem Schritt erstellt werden, wobei der spezifische Typ basierend auf den gegebenen Parametern ausgewählt wird. Stellen Sie sich das Serialisierungssystem vor, wo Sie Ihren Serializer erstellen und das gewünschte Objekt in einem Aufruf erstellen.

    • Konstruieren eines komplexen Objekts Schritt für Schritt: Builder-Muster

    • Ein einfaches Objekt wird mit einer einzigen Methode erstellt: Fabrikmethodenmuster

    • Erstellen eines Objekts mit mehreren Factory-Methoden: Abstraktes Factory-Muster

    Beide sind Creational Patterns, um ein Objekt zu erstellen.

    1) Factory Pattern – Angenommen, Sie haben eine Superklasse und N Unterklassen. Das Objekt wird erstellt, abhängig davon, welcher Parameter / Wert übergeben wurde.

    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. 

    Zuerst einige allgemeine Dinge, die meiner Argumentation folgen:

    Die große Herausforderung beim Entwurf großer Softwaresysteme ist, dass sie flexibel und unkompliziert zu ändern sind. Aus diesem Grund gibt es einige Metriken wie Kopplung und Kohäsion. Um Systeme zu erreichen, die leicht in ihrer functionalität geändert oder erweitert werden können, ohne das gesamte System von Grund auf neu zu entwickeln, können Sie den Designprinzipien folgen (wie SOLID, etc.). Nach einiger Zeit haben einige Entwickler erkannt, dass wenn sie diesen Prinzipien folgen, es einige ähnliche Lösungen gibt, die zu ähnlichen Problemen gut funktionieren. Diese Standardlösungen erwiesen sich als die Entwurfsmuster.

    Die Entwurfsmuster sollen Sie also dabei unterstützen, den allgemeinen Entwurfsprinzipien zu folgen, um lose gekoppelte Systeme mit hoher Kohäsion zu erreichen.

    Beantwortung der Frage:

    Wenn Sie den Unterschied zwischen zwei Mustern untersuchen, müssen Sie sich fragen, welches Muster Ihr System flexibler macht. Jedes Muster hat seinen eigenen Zweck, Abhängigkeiten zwischen classn in Ihrem System zu organisieren.

    Das abstrakte Fabrikmuster: GoF: “Stellen Sie eine Schnittstelle zum Erstellen von Familien verwandter oder abhängiger Objekte ohne Angabe ihrer konkreten classn bereit.”

    Was bedeutet das: Durch die Bereitstellung einer solchen Schnittstelle wird der Aufruf des Konstruktors jedes Produkts der Familie in der Factory-class gekapselt. Und da dies die einzige Stelle in Ihrem System ist, an der diese Konstruktoren aufgerufen werden, können Sie Ihr System ändern, indem Sie eine neue Factory-class implementieren. Wenn Sie die Darstellung der Fabrik durch eine andere austauschen, können Sie eine ganze Reihe von Produkten austauschen, ohne den Großteil Ihres Codes zu berühren.

    Das Builder-Muster: GoF: “Trennen Sie die Konstruktion eines komplexen Objekts von seiner Darstellung, damit der gleiche Konstruktionsprozess verschiedene Darstellungen erzeugen kann.”

    Was bedeutet das: Sie kapseln den Konstruktionsprozess in einer anderen class, dem sogenannten Director (GoF). Dieser Director enthält den Algorithmus zum Erstellen neuer Exemplare des Produkts (z. B. ein komplexes Produkt aus anderen Teilen zusammensetzen). Um die wesentlichen Teile des gesamten Produkts zu erstellen, verwendet der Regisseur einen Builder. Indem Sie den Builder im Director austauschen, können Sie den gleichen Algorithmus zum Erstellen des Produkts verwenden, aber die Darstellungen der einzelnen Teile (und damit die Darstellung des Produkts) ändern. Um Ihr System in der Darstellung des Produkts zu erweitern oder zu modifizieren, müssen Sie lediglich eine neue Builder-class implementieren.

    Kurz gesagt: Das Ziel des Abstract Factory Pattern ist es, eine Reihe von Produkten auszutauschen, die zusammen verwendet werden. Das Builder-Muster dient dazu, den abstrakten Algorithmus zum Erstellen eines Produkts zu verkapseln, 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 Patterns ist. Ja, sie sind beide schöpferische Muster, aber die Hauptabsicht der Muster ist ganz anders.

    Ein auffälliger Unterschied zwischen Builder und Fabrik, den ich ausmachen 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 Schnittstelle können wir das Auto auf folgende Weise bekommen:

      int main() { BadCar = new Car(false,false,true,4,4); } 

    Aber was passiert, wenn beim Erstellen der Sitze etwas passiert ??? SIE WERDEN DAS OBJEKT NICHT ERHALTEN // 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, selbst wenn eine Operation fehlschlägt, würden Sie immer noch das Auto bekommen.

    Mag sein, dass Auto später nicht perfekt funktioniert, aber Sie hätten das Objekt.

    Weil Factory-Methode gibt Ihnen das Auto in Einzelruf, während der Builder eins nach dem anderen baut.

    Es hängt zwar von den Bedürfnissen des Gutes ab, für welches man sich entscheidet.

    Dies ist ein kreatives Muster, da es zur Steuerung der classninstanziierung verwendet wird. Das Builder-Muster wird verwendet, um komplexe Objekte mit Bestandteilen zu erstellen, die in der gleichen Reihenfolge oder mit einem bestimmten Algorithmus erstellt werden müssen. Eine externe class, die als Director bezeichnet wird, steuert den Konstruktionsalgorithmus.

    Probe

     using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApp_Design_Patterns { class BuilderDesignPattern { static void Main(string[] args) { //create a constructor object to start building Kid aKid = new Kid(); aKid.Name = "Elizabeth"; //Elizabeth use Monkey mold to make a monkey Console.WriteLine("{0} start making a monkey", aKid.Name); AnimalBuilder builderA = new MonkeyBuilder(); aKid.MakeAnimal(builderA); builderA.aAnimal.ShowMe(); //Elizabeth use Kitten mold to make a kitten Console.WriteLine("{0} start making a kitten", aKid.Name); AnimalBuilder builderB = new KittenBuilder(); aKid.MakeAnimal(builderB); builderB.aAnimal.ShowMe(); Console.Read(); } } public abstract class AnimalBuilder { public Animal aAnimal; public abstract void BuildAnimalHeader(); public abstract void BuildAnimalBody(); public abstract void BuildAnimalLeg(); public abstract void BuildAnimalArm(); public abstract void BuildAnimalTail(); } public class MonkeyBuilder : AnimalBuilder { public MonkeyBuilder() { aAnimal = new Monkey(); } public override void BuildAnimalHeader() { aAnimal.Head = "Moneky's Head has been built"; } public override void BuildAnimalBody() { aAnimal.Body = "Moneky's Body has been built"; } public override void BuildAnimalLeg() { aAnimal.Leg = "Moneky's Leg has been built"; } public override void BuildAnimalArm() { aAnimal.Arm = "Moneky's Arm has been built"; } public override void BuildAnimalTail() { aAnimal.Tail = "Moneky's Tail has been built"; } } public class KittenBuilder : AnimalBuilder { public KittenBuilder() { aAnimal = new Kitten(); } public override void BuildAnimalHeader() { aAnimal.Head = "Kitten's Head has been built"; } public override void BuildAnimalBody() { aAnimal.Body = "Kitten's Body has been built"; } public override void BuildAnimalLeg() { aAnimal.Leg = "Kitten's Leg has been built"; } public override void BuildAnimalArm() { aAnimal.Arm = "Kitten's Arm has been built"; } public override void BuildAnimalTail() { aAnimal.Tail = "Kitten's Tail has been built"; } } public abstract class Animal { public string Head { get; set; } public string Body { get; set; } public string Leg { get; set; } public string Arm { get; set; } public string Tail { get; set; } //helper method for demo the Polymorphism, so we can //easily tell what type object it is from client. public abstract void Eat(); //helper method for demo the result from client public void ShowMe() { Console.WriteLine(Head); Console.WriteLine(Body); Console.WriteLine(Leg); Console.WriteLine(Arm); Console.WriteLine(Tail); Eat(); } } public class Monkey : Animal { //helper method to show monkey's property for demo purpose public override void Eat() { Console.WriteLine("Since I am Monkey, I like to eat banana"); } } public class Kitten : Animal { public override void Eat() { Console.WriteLine("Since I am Kitten, I like to eat kitten food"); } } public class Kid { public string Name { get; set; } //construct process to build an animal object, //after this process completed, a object //will be consider as a ready to use object. public void MakeAnimal(AnimalBuilder aAnimalBuilder) { aAnimalBuilder.BuildAnimalHeader(); aAnimalBuilder.BuildAnimalBody(); aAnimalBuilder.BuildAnimalLeg(); aAnimalBuilder.BuildAnimalArm(); aAnimalBuilder.BuildAnimalTail(); } } } 

    Builder und Abstract Factory haben für verschiedene Zwecke gedacht. Je nach Anwendungsfall müssen Sie ein geeignetes Designmuster auswählen.

    Builder hervorstechende Merkmale:

    1. Das Builder-Muster erstellt ein komplexes Objekt mit einfachen Objekten und einer schrittweisen Vorgehensweise
    2. Eine Builder-class erstellt das endgültige Objekt Schritt für Schritt. Dieser Builder ist unabhängig von anderen Objekten
    3. Ersatz für Factory-Methode / Abstract Factory in diesem Szenario: Zu viele Argumente, die vom Client-Programm an die Factory-class übergeben werden, die errorsanfällig sein kann
    4. Einige der Parameter können optional sein, anders als in Factory, wo alle Parameter gesendet werden müssen

    Fabrik (einfache Fabrik) hervorstechende Merkmale:

    1. Kreatives Muster
    2. Basierend auf inheritance
    3. Factory gibt eine Factory-Methode (Schnittstelle) zurück, die wiederum Concrete Object zurückgibt
    4. Sie können neue Concrete Objects für die Schnittstelle ersetzen und der Client (Aufrufer) sollte nicht alle konkreten Implementierungen kennen
    5. Der Client greift immer nur auf die Schnittstelle zu und Sie können Details zur Objekterstellung in der Factory-Methode ausblenden.

    Oft beginnen Designs mit der Factory-Methode (weniger kompliziert, anpassbarer, Subklassen vermehrt sich) und entwickeln sich zu Abstract Factory , Prototype oder Builder (flexibler, komplexer)

    Sehen Sie sich verwandte Beiträge an:

    Builder in separater class halten (fließende Schnittstelle)

    Entwurfsmuster: Factory vs Factory-Methode vs abstrakte Fabrik

    Weitere Informationen finden Sie in den folgenden Artikeln:

    Quellenherstellung

    Journaldev

    Abstraktes Factory & Builder-Muster sind beide Creational-Muster, aber mit unterschiedlicher Absicht.

    Abstract Factory Pattern betont die Objekt-Erstellung für Familien verwandter Objekte, in denen:

    • Jede Familie ist eine Gruppe von classn, die von einer gemeinsamen Basisklasse / Schnittstelle abgeleitet sind.
    • Jedes Objekt wird sofort als Ergebnis eines Anrufs zurückgegeben.

    Das Builder-Muster konzentriert sich darauf, ein komplexes Objekt Schritt für Schritt aufzubauen. Es entkoppelt die Repräsentation von dem process des Konstruierens des komplexen Objekts, so dass derselbe Konstruktionsprozess für verschiedene Repräsentationen verwendet werden kann.

    • Builder-Objekt kapselt die Konfiguration des komplexen Objekts.
    • Director-Objekt kennt das Protokoll der Verwendung des Builders, wobei das Protokoll alle logischen Schritte definiert, die zum Erstellen des komplexen Objekts erforderlich sind.

    Builder Pattern und Factory-Muster scheinen identisch, da beide Objekte für Sie erstellen.

    Du musst genauer hinsehen

    Dieses Beispiel aus dem wirklichen Leben wird den Unterschied zwischen den beiden klarer machen.

    Du bist zum Fastfood-Restaurant gegangen und bestellst Essen .

    1) Welches Essen?

    Pizza

    2) Welche Beläge?

    Paprika, Tomaten, BBQ Huhn, keine Ananas

    So verschiedene Arten von Lebensmitteln werden von Factory-Muster gemacht, aber die verschiedenen Varianten eines bestimmten Lebensmittels werden von Builder-Muster gemacht.

    Verschiedene Arten von Lebensmitteln

    Pizza, Burger, Pasta

    Varianten von Pizza

    Nur Käse, Käse + Tomaten + Capsicum, Käse + Tomaten usw.

    Codebeispiel

    Sie können die Beispielcode-Implementierung beider Muster hier sehen
    Erbauer-Muster
    Fabrikmuster

    Beide sind sehr ähnlich, aber wenn Sie eine große Anzahl von Parametern für die Objekterstellung haben, einige davon optional mit einigen Standardwerten, gehen Sie zum Builder-Muster.

     +-------------------------------------------------------------------+---------------------------------------------------+ | 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 | +-------------------------------------------------------------------+---------------------------------------------------+ 

    Teleskop-Konstruktor-Muster

    Analogie:

    • Fabrik: Stellen Sie sich ein Restaurant vor. Die Kreation des “heutigen Essens” ist ein Fabrikmuster, denn Sie sagen der Küche, “Holen Sie mir das heutige Essen”, und die Küche (Fabrik) entscheidet anhand versteckter Kriterien, welches Objekt erzeugt werden soll.
    • Builder: Der Builder wird angezeigt, wenn Sie eine benutzerdefinierte Pizza bestellen. In diesem Fall sagt der Kellner dem Koch (Erbauer): “Ich brauche eine Pizza; füge Käse, Zwiebeln und Speck hinzu!” Daher stellt der Builder die Attribute bereit, die das generierte Objekt haben sollte, blendet aber aus, wie sie festgelegt werden sollen.

    Höflichkeit

    Eine komplexe Konstruktion besteht darin, dass das zu konstruierende Objekt aus verschiedenen anderen Objekten besteht, die durch Abstraktionen repräsentiert werden.

    Betrachten Sie ein Menü in McDonalds. Ein Menü enthält ein Getränk, eine Haupt- und eine Seite. Abhängig davon, welche Abkömmlinge der einzelnen Abstraktionen zusammengesetzt sind, hat das erstellte Menü eine andere Darstellung.

    1. Beispiel: Cola, Big Mac, Pommes Frites
    2. Beispiel: Sprite, Nuggets, Curly Fries

    Dort haben wir zwei Instanzen des Menüs mit verschiedenen Darstellungen. Der process des Aufbaus bleibt derselbe. Sie erstellen ein Menü mit einem Getränk, einer Haupt- und einer Seite.

    Mit dem Builder-Muster 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 in dem Direktor eingekapselt, während die Builder verwendet werden, um die integralen Teile zu erzeugen. Die Variation des verwendeten Builders im Algorithmus des Directors führt zu einer anderen Darstellung, da andere Teile zu einem Menü zusammengesetzt werden. Die Art und Weise, wie ein Menü erstellt wird, bleibt unverändert.

    Build-Muster betont die Komplexität des Erstellens von Objekten (getriggers durch “Steps”)

    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 erstellen muss. Im Fabrikmuster bauen Sie mit der abstrakten class das spezifische Objekt direkt auf.

    Hier agiert die Builder-class als Vermittler zwischen Hauptklasse und spezifischen Typklassen. Mehr Abstraktion.

    Ich glaube, die Verwendung und der Unterschied zwischen Factory & Builder-Mustern kann in einem bestimmten Zeitraum leichter verstanden / geklärt werden, wenn Sie an der gleichen Code-Basis und den sich ändernden Anforderungen gearbeitet haben.

    Aus meiner Erfahrung starten Sie normalerweise mit einem Factory-Muster, das einige statische Erstellungsmethoden enthält. Wenn Ihre Objekthierarchie komplexer wird (oder Sie weitere Typen hinzufügen), haben Sie wahrscheinlich am Ende Ihre Methoden mit mehr Parametern gefüllt und Sie müssen Ihr Factory-Modul neu kompilieren. All diese Dinge erhöhen die Komplexität Ihrer Erstellungsmethoden, verringern die Lesbarkeit und machen das Erstellungsmodul fragiler.

    Dieser Punkt wird möglicherweise der Übergangspunkt sein. Übergang vom Factory- zum Builder-Muster. Indem Sie dies tun, erstellen Sie ein Wrapper-Modul um die Konstruktionsparameter, und dann können Sie neue (ähnliche) Objekte darstellen, indem Sie (vielleicht) mehr Abstraktionen hinzufügen, ohne Ihre Erstellungslogik zu berühren. Sie hatten also weniger komplexe Logik und kompilierten Quellcode neu

    Ehrlich gesagt, bezieht man sich auf etwas, das “in einem oder mehreren Schritten ein Objekt geschaffen hat, ist der Unterschied”, da der einzige Diversity-Faktor nicht ausreichte, um sie zu unterscheiden, da ich für fast alle Fälle beide Möglichkeiten nutzen konnte jetzt ohne irgendeinen Nutzen zu erfahren. Das ist es, worüber ich letztendlich nachgedacht habe.

    Abstrakte Fabrik ist dem Erbauer insofern ähnlich, als sie auch komplexe Objekte konstruieren kann. Der Hauptunterschied besteht darin, dass das Builder-Muster sich darauf konzentriert, ein komplexes Objekt Schritt für Schritt aufzubauen. Der Schwerpunkt von Abstract Factor liegt auf Familien von Produktobjekten (entweder einfach oder komplex).

    Erbauer und abstrakte Fabrik

    Das Builder-Entwurfsmuster ist dem Muster der abstrakten Fabrik in gewissem Maße sehr ähnlich. Deshalb ist es wichtig, zwischen den Situationen, in denen das eine oder das andere verwendet wird, unterscheiden zu können. Im Fall der abstrakten Fabrik verwendet der Kunde die Methoden der Fabrik, um eigene Objekte zu erzeugen. Im Builder-Fall wird die Builder-class angewiesen, wie das Objekt erstellt wird, und danach wird danach gefragt, aber die Art, wie die class zusammengesetzt wird, hängt von der Builder-class ab, wobei dieses Detail den Unterschied zwischen den beiden Mustern darstellt.

    Gemeinsame Schnittstelle für Produkte

    In der Praxis haben die von den Betonbauern geschaffenen Produkte eine deutlich andere Struktur, so dass, wenn es keinen Grund gibt, unterschiedliche Produkte eine gemeinsame Elternklasse abzuleiten. Dies unterscheidet auch das Builder-Muster von dem Abstrakt-Fabrik-Muster, das Objekte erzeugt, die von einem gemeinsamen Typ abgeleitet sind.

    Von: http://www.oodesign.com/builder-pattern.html

    Meiner Meinung nach wird 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 hilft, die Erstellung eines Teils vom 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 Factory-Muster angeben, dass Sie Objekte einer gemeinsamen Familie erstellen möchten, und Sie möchten, dass es gleichzeitig erstellt wird. Es wird für einfachere Objekte verwendet.

    Beide Muster kommen aus der gleichen Notwendigkeit: Verstecke die Konstruktionslogik eines komplexen Objekts vor irgendeinem Client-Code … aber was macht ein Objekt “komplex” (oder manchmal kompliziert)? Hauptsächlich ist dies auf Abhängigkeiten zurückzuführen, oder vielmehr auf den Zustand eines Objekts, das aus mehreren Teilzuständen besteht. Sie können Abhängigkeiten nach Konstruktor einfügen, um den ursprünglichen Objektstatus zu setzen, aber ein Objekt benötigt möglicherweise eine Menge von ihnen, einige sind in einem Standard-Anfangszustand (nur weil wir gelernt haben sollten, dass eine Standardabhängigkeit auf null nicht die sauberste Art ist) ) und einige andere in einen Zustand versetzt, der von einer bestimmten Bedingung gesteuert wird. Darüber hinaus gibt es Objekteigenschaften, die eine Art von “nicht erkennbaren Abhängigkeiten” sind, aber auch sie können optionale Zustände annehmen

    Es gibt zwei bekannte Möglichkeiten, diese Komplexität zu beherrschen:

    • Zusammensetzung / Aggregation: Konstruiere ein Objekt, konstruiere seine abhängigen Objekte und verbinde es dann. Hier kann ein Builder den process, der die Regeln für die Konstruktion der Komponente bestimmt, transparent und flexibel gestalten
    • Polymorphismus: Konstruktionsregeln werden direkt in Subtypdefinitionen deklariert, so dass Sie für jeden Subtyp eine Reihe von Regeln haben und einige Bedingungen entscheiden, welche dieser Regeln für das Konstruieren des Objekts gilt. Eine Fabrik passt perfekt in dieses Szenario

    Nichts verhindert, diese beiden Ansätze zu vermischen. Eine Produktfamilie kann die Erstellung von Objekten mit einem Builder abstrahieren. Ein Builder kann mithilfe von Factorys ermitteln, welches Komponentenobjekt instanziiert wird

    meiner bescheidenen Meinung nach

    Builder ist eine Art komplexere Factory.

    Aber im Builder können Sie Objekte mit anderen Fabriken instanziieren , die zum Erstellen eines endgültigen und gültigen Objekts benötigt werden.

    Wenn Sie also über die Evolution von “Creational Patterns” nach Komplexität sprechen, können Sie auf diese Weise darüber nachdenken:

     Dependency Injection Container -> Service Locator -> Builder -> Factory 

    Das Factory-Muster erzeugt zur Laufzeit eine konkrete Implementierung einer class, dh es besteht hauptsächlich die Absicht, Polymorphie zu verwenden, damit Unterklassen entscheiden können, welche class instanziiert werden soll. Dies bedeutet, dass zum Zeitpunkt der Kompilierung die genaue class, die erstellt wird, nicht bekannt ist, während das Builder-Muster hauptsächlich das Problem der teleskopierenden Konstruktoren antipattern betrifft, das aufgrund einer großen Anzahl von optionalen Feldern einer class entsteht. Im Builder-Muster gibt es keine Vorstellung von Polymorphie, da wir wissen, welches Objekt wir zur Kompilierzeit konstruieren wollen.

    Das einzige gemeinsame Thema dieser beiden Muster ist das Verbergen von Konstruktoren und Objekterzeugung hinter Fabrikmethoden und die Erstellungsmethode für eine verbesserte Objektkonstruktion.

    Mit dem Factory-Muster können Sie gleichzeitig ein Objekt erstellen, während Sie mit dem Builder-Muster den Erstellungsprozess eines Objekts unterbrechen können. Auf diese Weise können Sie während der Erstellung eines Objekts verschiedene functionen hinzufügen.

    Ein Beispiel

    1) mit abstrakten Fabrik:

     GUIFactory factory = new WindowsGUIFactory(); Button button = factory.createButton(); // **creates a WindowsButton** 

    2) mit Builder:

     GUIBuilder builder = new WindowsGUIBuilder(); Button button = builder.createButton(); // **creates a Button.** button.setOS = OSEnum.Windows; 

    Da es keine WindowsButton-class gibt, muss er (der button.setOS = windows ) für die korrekte button.setOS = windows der Schaltfläche verantwortlich sein, dh: button.setOS = windows .

    Es ist vergleichbar mit TPH vs TPT im DB-Design zu vergleichen.