Поиск…


замечания

Отделяет построение сложного объекта от его представления, так что один и тот же процесс построения может создавать различные представления.

  • Отделите логику от представления.
  • Логика повторного использования для работы с различными наборами данных.

Builder Pattern / C # / Свободный интерфейс

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;
    }
}

Пример использования:

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

Builder Pattern / Java-реализация

Шаблон Builder позволяет вам создать экземпляр класса со многими необязательными переменными легко читаемым способом.

Рассмотрим следующий код:

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

}

Это все хорошо и хорошо, если все параметры необходимы. Что делать, если есть много других переменных и / или некоторые из них являются необязательными? Вы не хотите создавать большое количество конструкторов с каждой возможной комбинацией требуемых и необязательных параметров, потому что их трудно поддерживать и для разработчиков понимать. Вы также можете не иметь длинный список параметров, в которых многие, возможно, должны быть введены пользователем пользователем как null.

Шаблон Builder создает внутренний класс Builder, который используется для создания только необходимых необязательных переменных. Это делается с помощью методов для каждой необязательной переменной, которые принимают тип переменной как параметр и возвращают объект Builder, чтобы методы могли быть связаны друг с другом. Любые требуемые переменные помещаются в конструктор Builder, так что их нельзя игнорировать.

Builder также включает метод build() который возвращает объект, в котором он находится, и должен быть вызван в конце цепочки вызовов метода при создании объекта.

Следуя предыдущему примеру, этот код использует шаблон Builder для класса Computer.

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

Пример использования этого класса:

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();
    }

}

В этом примере показано, как шаблон-застройщик может обеспечить большую гибкость в создании класса с небольшим усилием. Объект «Компьютер» может быть реализован на основе желаемой конфигурации вызывающих абонентов в удобном для чтения виде с минимальными усилиями.

Шаблон Builder в Java с композицией

Намерение:

Отделить построение сложного объекта от его представления, чтобы тот же процесс построения мог создавать различные представления

Шаблон Builder полезен, когда у вас есть несколько обязательных атрибутов и множество необязательных атрибутов для создания объекта. Чтобы создать объект с различными обязательными и необязательными атрибутами, вам необходимо предоставить сложный конструктор для создания объекта. Шаблон Builder обеспечивает простой пошаговый процесс для создания сложного объекта.

Случай использования в реальной жизни:

Различные пользователи в FaceBook имеют разные атрибуты, которые состоят из обязательного атрибута, такого как имя пользователя и необязательные атрибуты, такие как UserBasicInfo и ContactInfo. Некоторые пользователи просто предоставляют базовую информацию. Некоторые пользователи предоставляют подробную информацию, включая контактную информацию. В отсутствие шаблона Builder вам необходимо предоставить конструктор со всеми обязательными и необязательными параметрами. Но шаблон Builder упрощает процесс построения, предоставляя простой пошаговый процесс для построения сложного объекта.

Подсказки:

  1. Предоставьте статический вложенный класс строителя.
  2. Предоставить конструктор для обязательных атрибутов объекта.
  3. Предоставлять методы setter и getter для необязательных атрибутов объекта.
  4. Верните один и тот же объект Builder после установки дополнительных атрибутов.
  5. Предоставить метод build (), который возвращает сложный объект

Фрагмент кода:

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

выход:

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

Объяснение:

  1. FaceBookUser - сложный объект с атрибутами ниже, используя состав:

    String userName;
    UserBasicInfo userInfo;
    ContactInfo contactInfo;
    
  2. FaceBookUserBuilder - это класс статического строителя, который содержит и создает FaceBookUser .

  3. userName - это только обязательный параметр для создания FaceBookUser

  4. FaceBookUserBuilder создает FaceBookUser , устанавливая дополнительные параметры: UserBasicInfo и ContactInfo

  5. Этот пример иллюстрирует три разных FaceBookUsers с различными атрибутами, построенными из Builder.

    1. fbUser1 был создан как FaceBookUser только с атрибутом userName
    2. fbUser2 был создан как FaceBookUser с именем пользователя и UserBasicInfo
    3. fbUser3 был создан как FaceBookUser с именем пользователя, UserBasicInfo и ContactInfo

В приведенном выше примере композиция использовалась вместо дублирования всех атрибутов FaceBookUser в классе Builder.

В созданных шаблонах мы сначала начнем с простого шаблона, такого как FactoryMethod и перейдем к более гибким и сложным шаблонам, таким как AbstractFactory и Builder .

Java / Ломбок

import lombok.Builder;

@Builder
public class Email {

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

}

Пример использования:

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

Расширенный шаблон Builder с выражением Java Lambda Expression

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;
 }
}

Старый путь

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

Расширенный способ:

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

}

Использование:

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

См. Https://medium.com/beingprofessional/think-functional-advanced-builder-pattern-using-lambda-284714b85ed5#.d9sryx3g9.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow