Recherche…


Remarques

Séparer la construction d'un objet complexe de sa représentation afin qu'un même processus de construction puisse créer différentes représentations.

  • Séparer la logique de la représentation.
  • Réutiliser la logique pour travailler avec différents ensembles de données.

Modèle de générateur / C # / Interface fluide

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

Exemple d'utilisation:

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

Modèle de générateur / Implémentation Java

Le modèle Builder vous permet de créer une instance d'une classe avec de nombreuses variables facultatives d'une manière facile à lire.

Considérez le code suivant:

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

}

Tout va bien si tous les paramètres sont nécessaires. Et s'il y a beaucoup plus de variables et / ou certaines d'entre elles sont facultatives? Vous ne voulez pas créer un grand nombre de constructeurs avec chaque combinaison possible de paramètres obligatoires et facultatifs, car cela devient difficile à gérer et à comprendre pour les développeurs. Il se peut également que vous ne souhaitiez pas avoir une longue liste de paramètres dans lesquels l'utilisateur peut avoir à saisir beaucoup de paramètres nuls.

Le modèle de générateur crée une classe interne appelée Builder qui permet d'instancier uniquement les variables facultatives souhaitées. Cela se fait par des méthodes pour chaque variable facultative qui prend le type de variable comme paramètre et renvoie un objet Builder afin que les méthodes puissent être chaînées les unes avec les autres. Toutes les variables requises sont placées dans le constructeur Builder afin qu'elles ne puissent pas être omises.

Le générateur inclut également une méthode appelée build() qui renvoie l'objet dans lequel elle se trouve et doit être appelée à la fin de la chaîne d'appels de méthode lors de la construction de l'objet.

À la suite de l'exemple précédent, ce code utilise le modèle Builder pour la classe 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);
        }
    }
}

Un exemple d'utilisation de cette classe:

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

}

Cet exemple montre comment le modèle de générateur peut permettre une grande flexibilité dans la création d'une classe avec un effort assez réduit. L'objet Ordinateur peut être implémenté en fonction de la configuration souhaitée par les appelants dans un format facile à lire et sans effort.

Modèle de constructeur en Java avec composition

Intention:

Séparer la construction d'un objet complexe de sa représentation afin qu'un même processus de construction puisse créer différentes représentations

Le modèle de générateur est utile lorsque vous avez peu d'attributs obligatoires et de nombreux attributs facultatifs pour construire un objet. Pour créer un objet avec différents attributs obligatoires et facultatifs, vous devez fournir un constructeur complexe pour créer l'objet. Le modèle de générateur fournit un processus pas à pas simple pour construire un objet complexe.

Cas d'utilisation réel:

Différents utilisateurs de FaceBook ont ​​des attributs différents, qui consistent en des attributs obligatoires tels que le nom d'utilisateur et des attributs facultatifs tels que UserBasicInfo et ContactInfo. Certains utilisateurs fournissent simplement des informations de base. Certains utilisateurs fournissent des informations détaillées, y compris les informations de contact. En l'absence de modèle Builder, vous devez fournir un constructeur avec tous les paramètres obligatoires et facultatifs. Mais le modèle Builder simplifie le processus de construction en fournissant un processus simple, étape par étape, pour construire l'objet complexe.

Conseils:

  1. Fournit une classe de générateur imbriquée statique.
  2. Fournit un constructeur pour les attributs obligatoires de l'objet.
  3. Fournit des méthodes de réglage et de lecture pour les attributs optionnels de l'objet.
  4. Renvoie le même objet Builder après la définition des attributs facultatifs.
  5. Fournit la méthode build (), qui renvoie un objet complexe

Extrait de code:

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

sortie:

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

Explication:

  1. FaceBookUser est un objet complexe dont les attributs ci-dessous utilisent la composition:

    String userName;
    UserBasicInfo userInfo;
    ContactInfo contactInfo;
    
  2. FaceBookUserBuilder est une classe de construction statique qui contient et construit FaceBookUser .

  3. userName est uniquement un paramètre obligatoire pour créer FaceBookUser

  4. FaceBookUserBuilder construit FaceBookUser en définissant des paramètres facultatifs: UserBasicInfo et ContactInfo

  5. Cet exemple illustre trois FaceBookUsers différents avec des attributs différents, construits à partir de Builder.

    1. fbUser1 a été construit comme FaceBookUser avec l'attribut userName uniquement
    2. fbUser2 a été construit comme FaceBookUser avec userName et UserBasicInfo
    3. fbUser3 a été créé avec FaceBookUser avec userName, UserBasicInfo et ContactInfo

Dans l'exemple ci-dessus, la composition a été utilisée au lieu de dupliquer tous les attributs de FaceBookUser dans la classe Builder.

Dans les modèles de création, nous commencerons par un modèle simple, comme FactoryMethod et FactoryMethod vers des modèles plus flexibles et complexes, tels que AbstractFactory et Builder .

Java / Lombok

import lombok.Builder;

@Builder
public class Email {

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

}

Exemple d'utilisation:

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

Modèle de générateur avancé avec une expression Java 8 Lambda

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

Ancienne voie

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

Manière avancée:

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

}

Usage:

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

Se référer: https://medium.com/beingprofessional/think-functional-advanced-builder-pattern-using-lambda-284714b85ed5#.d9sryx3g9



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow