Wir alle als Entwickler sind schon auf Situationen gestoßen, in denen wir ein Objekt erstellen müssen. Das Problem beim Versuch, eine generische Klasse für dieses Objekt zu entwerfen, besteht darin, dass es mehrere Formen annehmen kann. Ein einfaches Beispiel: die User-Klasse einer Plattform. Für einen normalen Benutzer benötigen wir möglicherweise nur eine E-Mail-Adresse und einen Benutzernamen. Für einen Plattformadministrator sind jedoch möglicherweise zusätzliche Attribute wie eine Telefonnummer erforderlich. Wir könnten auch einen Premium-Benutzer haben, für den ein zusätzliches Feld wie eine Kreditkartennummer usw. erforderlich ist.
Wie können wir also generisch vorgehen?
Angesichts dieses Problems einigte sich die Entwicklergemeinschaft auf ein beliebtes Erstellungsmuster: das Builder Design Pattern. Bei diesem Muster wird die Konstruktion eines komplexen Objekts von seiner Darstellung getrennt, sodass mehrere Objektvarianten mit demselben Konstruktionsprozess erstellt werden können.
Dieses Muster ist besonders nützlich bei Objekten mit vielen Attributen, von denen einige in bestimmten Fällen optional sein können, in anderen jedoch nicht, oder bei Objekten, die einen detaillierten Initialisierungsprozess erfordern. Es ermöglicht die flexible, schrittweise Erstellung von Objekten, ohne dass der Code übermäßig komplex oder der Konstruktor zu überlastet wird.
Abschnitte, die wir behandeln werden
Das Builder-Entwurfsmuster ist in den folgenden Fällen besonders nützlich:
Wenn ein Objekt viele Attribute hat, von denen einige optional sind: Um auf das Problem zurückzukommen, das wir am Anfang dieses Artikels gestellt haben, betrachten wir die User-Klasse. Basierend auf der von uns beschriebenen Logik könnten wir bei der Instanziierung dieser Benutzerklasse verschiedene Fälle haben: für einen regulären Benutzer, normalUser = new User("houda", "houda@gmail.com", null, null), für einen Administrator adminUser = neuer Benutzer("houda", "houda@gmail.com", "0657...", null) und für einen Premium-Benutzer premiumUser = neuer Benutzer("houda", "houda@gmail.com", null, „1234...“). Dies führt zu vielen Nullwerten in der Instanziierung.
Objekte mit einem mehrstufigen Erstellungsprozess: Ein Beispiel ist eine Order-Klasse. Der erste Schritt besteht darin, die Bestellung aufzugeben, die dann vorbereitet und schließlich geliefert wird. Die Vorbereitung eines Auftrags kann mehrere Schritte erfordern, und um die richtige Baureihenfolge sicherzustellen, ist das Builder-Entwurfsmuster sehr nützlich.
Unterstützung mehrerer Darstellungen desselben Objekts: Zum Beispiel eine Kleidungsklasse, die Attribute für Stoff, Farbe und Marke hat. Ein Kleidungsstück kann eine Hose, ein T-Shirt oder eine andere Art sein. Hier hilft das Builder-Muster dabei, verschiedene Darstellungen derselben Basisklasse zu erstellen.
Für jeden Fall, den wir im Abschnitt zuvor gesehen haben, werden wir die Implementierung des Builders sehen
class User { username: string; email: string; phoneNumber?: string; creditCard?: string; private constructor(builder: UserBuilder) { this.username = builder.username; this.email = builder.email; this.phoneNumber = builder.phoneNumber; this.creditCard = builder.creditCard; } public static get Builder() { return new UserBuilder(); } } class UserBuilder { username!: string; email!: string; phoneNumber?: string; creditCard?: string; public setUsername(username: string): UserBuilder { this.username = username; return this; } public setEmail(email: string): UserBuilder { this.email = email; return this; } public setPhoneNumber(phoneNumber: string): UserBuilder { this.phoneNumber = phoneNumber; return this; } public setCreditCard(creditCard: string): UserBuilder { this.creditCard = creditCard; return this; } public build(): User { return new User(this); } } // Usage const normalUser = User.Builder .setUsername("houda") .setEmail("houda@gmail.com") .build(); const adminUser = User.Builder .setUsername("houda") .setEmail("houda@gmail.com") .setPhoneNumber("0657....") .build(); const premiumUser = User.Builder .setUsername("houda") .setEmail("houda@gmail.com") .setCreditCard("1234....") .build();
class Order { private state: string; private constructor(builder: OrderBuilder) { this.state = builder.state; } public static get Builder() { return new OrderBuilder(); } public getState(): string { return this.state; } } class OrderBuilder { state: string = "Placed"; public prepareOrder(): OrderBuilder { if (this.state === "Placed") { this.state = "Prepared"; } return this; } public deliverOrder(): OrderBuilder { if (this.state === "Prepared") { this.state = "Delivered"; } return this; } public build(): Order { return new Order(this); } } // Usage const completedOrder = Order.Builder .prepareOrder() .deliverOrder() .build(); console.log(completedOrder.getState()); // "Delivered"
class Clothing { type: string; fabric: string; color: string; brand: string; private constructor(builder: ClothingBuilder) { this.type = builder.type; this.fabric = builder.fabric; this.color = builder.color; this.brand = builder.brand; } public static get Builder() { return new ClothingBuilder(); } } class ClothingBuilder { type!: string; fabric!: string; color!: string; brand!: string; public setType(type: string): ClothingBuilder { this.type = type; return this; } public setFabric(fabric: string): ClothingBuilder { this.fabric = fabric; return this; } public setColor(color: string): ClothingBuilder { this.color = color; return this; } public setBrand(brand: string): ClothingBuilder { this.brand = brand; return this; } public build(): Clothing { return new Clothing(this); } } // Usage const tShirt = Clothing.Builder .setType("T-Shirt") .setFabric("Cotton") .setColor("Blue") .setBrand("BrandA") .build(); const pants = Clothing.Builder .setType("Pants") .setFabric("Denim") .setColor("Black") .setBrand("BrandB") .build();
Das Builder-Entwurfsmuster ist aus mehreren wichtigen Gründen wichtig, insbesondere wenn es darum geht, die Komplexität der Objekterstellung zu bewältigen. Darum ist es so wertvoll:
Wenn ein Objekt viele Attribute hat, von denen einige optional sind oder in einer bestimmten Reihenfolge festgelegt werden müssen, bietet das Builder-Muster eine klare und strukturierte Möglichkeit, das Objekt zu erstellen.
Durch die Trennung der Objekterstellungslogik vom Objekt selbst macht das Builder-Muster den Code lesbarer und einfacher zu warten.
Anstatt mehrere Konstruktoren mit unterschiedlichen Parameterkombinationen zu haben, macht das Builder-Muster eine Konstruktorüberladung überflüssig.
Der Erbauer trennt die Konstruktion eines Objekts von seiner Darstellung. Das bedeutet, dass Sie die Konstruktion des Objekts ändern können, ohne seine Darstellung zu beeinflussen, oder umgekehrt.
Das Builder Design Pattern ist ein unverzichtbares Werkzeug für Entwickler, die sich mit der Erstellung komplexer Objekte befassen. Durch die Unterteilung des Konstruktionsprozesses in klare, überschaubare Schritte werden die Lesbarkeit, Wartbarkeit und Flexibilität des Codes verbessert. Unabhängig davon, ob Sie mit Objekten arbeiten, die viele Attribute haben, eine mehrstufige Konstruktion erfordern oder mehrere Konfigurationen unterstützen müssen, bietet das Builder-Muster eine elegante Lösung, die überkomplizierte Konstruktoren verhindert und Fehler reduziert.
Der Blog behandelte Folgendes:
Das obige ist der detaillierte Inhalt vonBeherrschung des Builder-Entwurfsmusters: Vereinfachung der Erstellung komplexer Objekte. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!