Suche…


Bemerkungen

Trennt die Konstruktion eines komplexen Objekts von seiner Darstellung, sodass derselbe Konstruktionsprozess verschiedene Darstellungen erstellen kann.

  • Trennen Sie die Logik von der Darstellung.
  • Verwenden Sie die Logik erneut, um mit anderen Daten zu arbeiten.

Builder Pattern / C # / Fließende Schnittstelle

public class Email
{
    public string To { get; set; }
    public string From { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
}

public class EmailBuilder
{
    private readonly Email _email;

    public EmailBuilder()
    {
        _email = new Email();
    }

    public EmailBuilder To(string address)
    {
        _email.To = address;
        return this;
    }

    public EmailBuilder From(string address)
    {
        _email.From = address;
        return this;
    }

    public EmailBuilder Subject(string title)
    {
        _email.Subject = title;
        return this;
    }

    public EmailBuilder Body(string content)
    {
        _email.Body = content;
        return this;
    }

    public Email Build()
    {
        return _email;
    }
}

Anwendungsbeispiel:

var emailBuilder = new EmailBuilder();
var email = emailBuilder
    .To("[email protected]")
    .From("[email protected]")
    .Subject("Email subject")
    .Body("Email content")
    .Build();

Builder Pattern / Java-Implementierung

Mit dem Builder-Muster können Sie auf einfache Weise eine Instanz einer Klasse mit vielen optionalen Variablen erstellen.

Betrachten Sie den folgenden Code:

public class Computer {

    public GraphicsCard graphicsCard;
    public Monitor[] monitors;
    public Processor processor;
    public Memory[] ram;
    //more class variables here...

    Computer(GraphicsCard g, Monitor[] m, Processer p, Memory ram) {
        //code omitted for brevity...
    }

    //class methods omitted...

}

Das ist alles gut und gut, wenn alle Parameter notwendig sind. Was ist, wenn es viel mehr Variablen gibt und / oder einige von ihnen optional sind? Sie möchten nicht mit jeder möglichen Kombination von erforderlichen und optionalen Parametern eine große Anzahl von Konstruktoren erstellen, da diese nur schwer zu verwalten und für Entwickler verständlich werden. Möglicherweise möchten Sie auch keine lange Liste von Parametern, in denen viele vom Benutzer als Null eingegeben werden müssen.

Das Builder-Muster erstellt eine innere Klasse namens Builder, mit der nur die gewünschten optionalen Variablen instanziiert werden. Dies geschieht durch Methoden für jede optionale Variable, die den Variablentyp als Parameter übernimmt und ein Builder-Objekt zurückgibt, sodass die Methoden miteinander verkettet werden können. Alle erforderlichen Variablen werden in den Builder-Konstruktor eingefügt, damit sie nicht ausgelassen werden können.

Der Builder enthält auch eine Methode namens build() die das Objekt zurückgibt, in dem es sich befindet und das am Ende der Kette von Methodenaufrufen beim build() des Objekts aufgerufen werden muss.

Aus dem vorherigen Beispiel folgt dieser Code das Builder-Muster für die Computer-Klasse.

public class Computer {

    private GraphicsCard graphicsCard;
    private Monitor[] monitors;
    private Processor processor;
    private Memory[] ram;
    //more class variables here...

    private Computer(Builder builder) {
        this.graphicsCard = builder.graphicsCard;
        this.monitors = builder.monitors;
        this.processor = builder.processor;
        this.ram = builder.ram;
    }

    public GraphicsCard getGraphicsCard() {
        return this.graphicsCard;
    }

    public Monitor[] getMonitors() {
        return this.monitors;
    }

    public Processor getProcessor() {
        return this.processor;
    }

    public Memory[] getRam() {
        return this.ram;
    }

    public static class Builder {
        private GraphicsCard graphicsCard;
        private Monitor[] monitors;
        private Processor processor;
        private Memory[] ram;

        public Builder(Processor p){
            this.processor = p;
        }

        public Builder graphicsCard(GraphicsCard g) {
            this.graphicsCard = g;
            return this;
        }

        public Builder monitors(Monitor[] mg) {
            this.monitors = mg;
            return this;
        }

        public Builder ram(Memory[] ram) {
            this.ram = ram;
            return this;
        }

        public Computer build() {
            return new Computer(this);
        }
    }
}

Ein Beispiel, wie diese Klasse verwendet wird:

public class ComputerExample {

    public static void main(String[] args) {
        Computer headlessComputer = new Computer.Builder(new Processor("Intel-i3"))
                .graphicsCard(new GraphicsCard("GTX-960"))
                .build();

        Computer gamingPC = new Computer.Builder(new Processor("Intel-i7-quadcode"))
                .graphicsCard(new GraphicsCard("DX11"))
                .monitors(new Monitor[] = {new Monitor("acer-s7"), new Monitor("acer-s7")})
                .ram(new Memory[] = {new Memory("2GB"), new Memory("2GB"), new Memory("2GB"), new Memory("2GB")})
                .build();
    }

}

Dieses Beispiel zeigt, wie das Builder-Muster eine große Flexibilität bei der Erstellung einer Klasse mit relativ geringem Aufwand ermöglicht. Das Computerobjekt kann basierend auf der gewünschten Konfiguration des Anrufers auf einfache Weise mit geringem Aufwand implementiert werden.

Baumustermuster in Java mit Zusammensetzung

Absicht:

Trennen Sie die Konstruktion eines komplexen Objekts von seiner Darstellung, sodass derselbe Konstruktionsprozess unterschiedliche Repräsentationen erstellen kann

Das Builder-Muster ist nützlich, wenn Sie wenige obligatorische Attribute und viele optionale Attribute zum Erstellen eines Objekts haben. Um ein Objekt mit unterschiedlichen obligatorischen und optionalen Attributen zu erstellen, müssen Sie einen komplexen Konstruktor zum Erstellen des Objekts bereitstellen. Das Konstruktionsmuster bietet einen einfachen schrittweisen Prozess zum Erstellen eines komplexen Objekts.

Anwendungsfall im echten Leben:

Verschiedene Benutzer in FaceBook haben unterschiedliche Attribute, die aus obligatorischen Attributen wie Benutzername und optionalen Attributen wie UserBasicInfo und ContactInfo bestehen. Einige Benutzer geben einfach grundlegende Informationen an. Einige Benutzer geben detaillierte Informationen an, einschließlich Kontaktinformationen. Wenn kein Builder-Muster vorhanden ist, müssen Sie einen Konstruktor mit allen obligatorischen und optionalen Parametern angeben. Das Builder-Muster vereinfacht jedoch den Konstruktionsprozess, indem es einen einfachen schrittweisen Prozess zum Erstellen des komplexen Objekts vorsieht.

Tipps:

  1. Stellen Sie eine statische verschachtelte Builder-Klasse bereit.
  2. Konstruktor für obligatorische Objektattribute bereitstellen.
  3. Stellen Sie Setter- und Getter-Methoden für optionale Objektattribute bereit.
  4. Geben Sie dasselbe Builder-Objekt zurück, nachdem Sie optionale Attribute festgelegt haben.
  5. Stellen Sie die build () -Methode bereit, die ein komplexes Objekt zurückgibt

Code-Auszug:

import java.util.*;

class UserBasicInfo{
    String nickName;
    String birthDate;
    String gender;
    
    public UserBasicInfo(String name,String date,String gender){
        this.nickName = name;
        this.birthDate = date;
        this.gender = gender;        
    }
    
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("Name:DOB:Gender:").append(nickName).append(":").append(birthDate).append(":").
        append(gender);
        return sb.toString();
    }
}

class ContactInfo{
    String eMail;
    String mobileHome;
    String mobileWork;
    
    public ContactInfo(String mail, String homeNo, String mobileOff){
        this.eMail = mail;
        this.mobileHome = homeNo;
        this.mobileWork = mobileOff;
    }    
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("email:mobile(H):mobile(W):").append(eMail).append(":").append(mobileHome).append(":").append(mobileWork);
        return sb.toString();
    }
}
class FaceBookUser {
    String userName;
    UserBasicInfo userInfo;
    ContactInfo contactInfo;
    
    public FaceBookUser(String uName){
        this.userName = uName;
    }    
    public void setUserBasicInfo(UserBasicInfo info){
        this.userInfo = info;
    }
    public void setContactInfo(ContactInfo info){
        this.contactInfo = info;
    }    
    public String getUserName(){
        return userName;
    }
    public UserBasicInfo getUserBasicInfo(){
        return userInfo;
    }
    public ContactInfo getContactInfo(){
        return contactInfo;
    }
    
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append("|User|").append(userName).append("|UserInfo|").append(userInfo).append("|ContactInfo|").append(contactInfo);
        return sb.toString();
    }
    
    static class FaceBookUserBuilder{
        FaceBookUser user;
        public FaceBookUserBuilder(String userName){
            this.user = new FaceBookUser(userName);
        }
        public FaceBookUserBuilder setUserBasicInfo(UserBasicInfo info){
            user.setUserBasicInfo(info);
            return this;
        }
        public FaceBookUserBuilder setContactInfo(ContactInfo info){
            user.setContactInfo(info);
            return this;
        }
        public FaceBookUser build(){
            return user;
        }
    }
}
public class BuilderPattern{
    public static void main(String args[]){
        FaceBookUser fbUser1 = new FaceBookUser.FaceBookUserBuilder("Ravindra").build(); // Mandatory parameters
        UserBasicInfo info = new UserBasicInfo("sunrise","25-May-1975","M");
        
        // Build User name + Optional Basic Info 
        FaceBookUser fbUser2 = new FaceBookUser.FaceBookUserBuilder("Ravindra").
                                                setUserBasicInfo(info).build();
        
        // Build User name + Optional Basic Info + Optional Contact Info
        ContactInfo cInfo = new ContactInfo("[email protected]","1111111111","2222222222");
        FaceBookUser fbUser3 = new FaceBookUser.FaceBookUserBuilder("Ravindra").
                                                setUserBasicInfo(info).
                                                setContactInfo(cInfo).build();
        
        System.out.println("Facebook user 1:"+fbUser1);
        System.out.println("Facebook user 2:"+fbUser2);
        System.out.println("Facebook user 3:"+fbUser3);
    }
}

Ausgabe:

Facebook user 1:|User|Ravindra|UserInfo|null|ContactInfo|null
Facebook user 2:|User|Ravindra|UserInfo|Name:DOB:Gender:sunrise:25-May-1975:M|ContactInfo|null
Facebook user 3:|User|Ravindra|UserInfo|Name:DOB:Gender:sunrise:25-May-1975:M|ContactInfo|email:mobile(H):mobile(W):[email protected]:1111111111:2222222222

Erläuterung:

  1. FaceBookUser ist ein komplexes Objekt mit folgenden Attributen unter Verwendung der Komposition:

    String userName;
    UserBasicInfo userInfo;
    ContactInfo contactInfo;
    
  2. FaceBookUserBuilder ist eine statische Builder-Klasse, die FaceBookUser enthält und FaceBookUser .

  3. userName ist nur ein obligatorischer Parameter zum Erstellen von FaceBookUser

  4. FaceBookUserBuilder FaceBookUser durch die Festlegung optionaler Parameter: UserBasicInfo und ContactInfo

  5. Dieses Beispiel zeigt drei verschiedene FaceBookUsers mit unterschiedlichen Attributen, die aus Builder erstellt wurden.

    1. fbUser1 wurde nur als FaceBookUser mit dem Attribut userName erstellt
    2. fbUser2 wurde als FaceBookUser mit userName und UserBasicInfo erstellt
    3. fbUser3 wurde als FaceBookUser mit Benutzername, UserBasicInfo und ContactInfo erstellt

Im obigen Beispiel wurde die Komposition verwendet, anstatt alle Attribute von FaceBookUser in der Builder-Klasse zu duplizieren.

In FactoryMethod Mustern beginnen wir zunächst mit einfachen Mustern wie FactoryMethod und bewegen FactoryMethod in Richtung flexiblerer und komplexerer Muster wie AbstractFactory und Builder .

Java / Lombok

import lombok.Builder;

@Builder
public class Email {

    private String to;
    private String from;
    private String subject;
    private String body;

}

Anwendungsbeispiel:

Email.builder().to("[email protected]")
        .from("[email protected]")
        .subject("Email subject")
        .body("Email content")
        .build();

Erweitertes Builder-Muster mit Java 8-Lambda-Ausdruck

public class Person {
private final String salutation;
private final String firstName;
private final String middleName;
private final String lastName;
private final String suffix;
private final Address address;
private final boolean isFemale;
private final boolean isEmployed;
private final boolean isHomewOwner;

public Person(String salutation, String firstName, String middleName, String lastName, String suffix, Address address, boolean isFemale, boolean isEmployed, boolean isHomewOwner) {
    this.salutation = salutation;
    this.firstName = firstName;
    this.middleName = middleName;
    this.lastName = lastName;
    this.suffix = suffix;
    this.address = address;
    this.isFemale = isFemale;
    this.isEmployed = isEmployed;
    this.isHomewOwner = isHomewOwner;
 }
}

Alter Weg

public class PersonBuilder {
private String salutation;
private String firstName;
private String middleName;
private String lastName;
private String suffix;
private Address address;
private boolean isFemale;
private boolean isEmployed;
private boolean isHomewOwner;

public PersonBuilder withSalutation(String salutation) {
    this.salutation = salutation;
    return this;
}

public PersonBuilder withFirstName(String firstName) {
    this.firstName = firstName;
    return this;
}

public PersonBuilder withMiddleName(String middleName) {
    this.middleName = middleName;
    return this;
}

public PersonBuilder withLastName(String lastName) {
    this.lastName = lastName;
    return this;
}

public PersonBuilder withSuffix(String suffix) {
    this.suffix = suffix;
    return this;
}

public PersonBuilder withAddress(Address address) {
    this.address = address;
    return this;
}

public PersonBuilder withIsFemale(boolean isFemale) {
    this.isFemale = isFemale;
    return this;
}

public PersonBuilder withIsEmployed(boolean isEmployed) {
    this.isEmployed = isEmployed;
    return this;
}

public PersonBuilder withIsHomewOwner(boolean isHomewOwner) {
    this.isHomewOwner = isHomewOwner;
    return this;
}

public Person createPerson() {
    return new Person(salutation, firstName, middleName, lastName, suffix, address, isFemale, isEmployed, isHomewOwner);
}

Fortgeschrittene Art:

public class PersonBuilder {
public String salutation;
public String firstName;
public String middleName;
public String lastName;
public String suffix;
public Address address;
public boolean isFemale;
public boolean isEmployed;
public boolean isHomewOwner;

public PersonBuilder with(
        Consumer<PersonBuilder> builderFunction) {
    builderFunction.accept(this);
    return this;
}


public Person createPerson() {
    return new Person(salutation, firstName, middleName,
            lastName, suffix, address, isFemale,
            isEmployed, isHomewOwner);
}

}

Verwendungszweck:

Person person = new PersonBuilder()
    .with($ -> {
        $.salutation = "Mr.";
        $.firstName = "John";
        $.lastName = "Doe";
        $.isFemale = false;
        $.isHomewOwner = true;
        $.address =
            new PersonBuilder.AddressBuilder()
                .with($_address -> {
                    $_address.city = "Pune";
                    $_address.state = "MH";
                    $_address.pin = "411001";
                }).createAddress();
    })
    .createPerson();

Siehe: https://medium.com/beingprofessional/think-functional-advanced-builder-pattern-using-lambda-284714b85ed5#.d9sryx3g9



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow