Java-builder mode

1 Introduction

In the process of software development, it is sometimes necessary to create a complex object, which is usually composed of multiple sub-components combined in certain steps. For example, a computer is assembled from CPU, motherboard, memory, hard disk, graphics card, chassis, monitor, keyboard, mouse and other components. Buyers cannot assemble the computer by themselves, but tell the computer sales company the configuration requirements of the computer. The computer sales company arranges technicians to assemble the computer, and then hands it to the buyer who wants to buy the computer.

There are many such examples in life, such as different characters in games, their gender, personality, ability, face shape, body shape, clothing, hairstyle and other characteristics are different; as well as the steering wheel, engine, frame, tires and other components in the car It is also diverse; the sender, recipient, subject, content, attachments, etc. of each email are also different.

All of the above products are composed of multiple parts, and each part can be flexibly selected, but the creation steps are similar. The creation of this type of product cannot be described by the factory model introduced earlier, and only the builder model can describe the creation of this type of product well.

2. Features of Builder Mode

The definition of the builder (Builder) pattern: refers to the separation of the construction of a complex object from its representation, so that the same construction process can create different representations. This design pattern is called the builder pattern. It decomposes a complex object into multiple simple objects, and then builds them step by step. It separates the change from the unchanging, that is, the components of the product are unchanged, but each part can be flexibly selected.

The main advantages of this mode are as follows:

  1. Good encapsulation, separation of construction and presentation.
  2. Good scalability, each specific builder is independent of each other, which is conducive to the decoupling of the system.
  3. The client does not need to know the details of the internal composition of the product, and the builder can gradually refine the creation process without any impact on other modules, which is convenient for controlling detailed risks.

** The disadvantages are as follows: **

  1. The components of the product must be the same, which limits its scope of use.
  2. If the internal changes of the product are complicated, and if the internal changes of the product occur, the builders must also modify them simultaneously, and the subsequent maintenance costs are relatively high.

The focus of the builder (Builder) mode and the factory mode are different: the builder mode focuses on the assembly process of the parts, while the factory method mode focuses more on the creation process of the parts, but the two can be used in combination.

3. The structure and realization of the pattern

The Builder model consists of four elements: product, abstract builder, concrete builder, and commander. Now we will analyze its basic structure and implementation methods.

  • The structure of the pattern

The main roles of the Builder mode are as follows.

  1. Product role (Product): It is a complex object containing multiple components, and each component is created by a specific builder.
  2. Abstract builder (Builder): It is an interface that contains abstract methods for creating various subcomponents of the product, and usually also contains a method getResult() that returns a complex product
  3. Concrete Builder: implements the Builder interface and completes the concrete creation method of each component of a complex product
  4. Director: It calls the component construction and assembly methods in the builder object to complete the creation of complex objects. The director does not involve specific product information

Insert picture description here

  • The realization of the pattern:

Product role: a complex object containing multiple components

class Product {
    
    
    private String partA;
    private String partB;
    private String partC;

    public void setPartA(String partA) {
    
    
        this.partA = partA;
    }

    public void setPartB(String partB) {
    
    
        this.partB = partB;
    }

    public void setPartC(String partC) {
    
    
        this.partC = partC;
    }

    public void show() {
    
    
        //显示产品的特性
    }
}

Abstract builder: Contains abstract methods for creating various sub-components of the product.

abstract class Builder {
    
    
    //创建产品对象
    protected Product product = new Product();

    public abstract void buildPartA();

    public abstract void buildPartB();

    public abstract void buildPartC();

    //返回产品对象
    public Product getResult() {
    
    
        return product;
    }
}

Concrete builder: implements the abstract builder interface

public class ConcreteBuilder extends Builder {
    
    
    public void buildPartA() {
    
    
        product.setPartA("建造 PartA");
    }

    public void buildPartB() {
    
    
        product.setPartB("建造 PartB");
    }

    public void buildPartC() {
    
    
        product.setPartC("建造 PartC");
    }
}

Commander: call the method in the builder to complete the creation of complex objects

class Director {
    
    
    private Builder builder;

    public Director(Builder builder) {
    
    
        this.builder = builder;
    }

    //产品构建与组装方法
    public Product construct() {
    
    
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.getResult();
    }
}

Customer class

public class Client {
    
    
    public static void main(String[] args) {
    
    
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        Product product = director.construct();
        product.show();
    }
}

4. Application of pattern

Use the Builder model to describe the living room decoration.

Analysis: Living room decoration is a complicated process, which includes wall decoration, TV selection, sofa purchase and layout, etc. The customer tells the project manager of the decoration requirements, and the project manager directs the decoration workers to step by step, and finally complete the decoration and layout of the entire living room, so this example is more suitable for implementation in the builder mode.

The living room here is the product, including the wall, TV, sofa and other components. Concrete decoration workers are concrete builders who are responsible for the decoration and the layout of walls, TVs and sofas. The project manager is the conductor and he is responsible for directing the decoration workers to carry out the decoration.

Insert picture description here

public class ParlourDecorator {
    
    
    public static void main(String[] args) {
    
    
        try {
    
    
            Decorator d;
            d = new ConcreteDecorator1();
            //d = new ConcreteDecorator2();
            ProjectManager m = new ProjectManager(d);
            Parlour p = m.decorate();
            p.show();
        } catch (Exception e) {
    
    
            System.out.println(e.getMessage());
        }
    }
}

//产品:客厅
class Parlour {
    
    
    private String wall;    //墙
    private String TV;    //电视
    private String sofa;    //沙发 

    public void setWall(String wall) {
    
    
        this.wall = wall;
    }

    public void setTV(String TV) {
    
    
        this.TV = TV;
    }

    public void setSofa(String sofa) {
    
    
        this.sofa = sofa;
    }

    public void show() {
    
    
        //...
    }
}

//抽象建造者:装修工人
abstract class Decorator {
    
    
    //创建产品对象
    protected Parlour product = new Parlour();

    public abstract void buildWall();

    public abstract void buildTV();

    public abstract void buildSofa();

    //返回产品对象
    public Parlour getResult() {
    
    
        return product;
    }
}

//具体建造者:具体装修工人1
class ConcreteDecorator1 extends Decorator {
    
    
    public void buildWall() {
    
    
        product.setWall("w1");
    }

    public void buildTV() {
    
    
        product.setTV("TV1");
    }

    public void buildSofa() {
    
    
        product.setSofa("sf1");
    }
}

//具体建造者:具体装修工人2
class ConcreteDecorator2 extends Decorator {
    
    
    public void buildWall() {
    
    
        product.setWall("w2");
    }

    public void buildTV() {
    
    
        product.setTV("TV2");
    }

    public void buildSofa() {
    
    
        product.setSofa("sf2");
    }
}

//指挥者:项目经理
class ProjectManager {
    
    
    private Decorator builder;

    public ProjectManager(Decorator builder) {
    
    
        this.builder = builder;
    }

    //产品构建与组装方法
    public Parlour decorate() {
    
    
        builder.buildWall();
        builder.buildTV();
        builder.buildSofa();
        return builder.getResult();
    }
}

5. Alternative creator mode

When the number of constructor parameters of a class exceeds 4, and some of these parameters are optional, consider using the constructor mode.

When a class has more than 4 constructor parameters, and some of these parameters are optional, we usually have two ways to construct its object. For example, we now have the following computer class Computer, in which cpu and ram are required parameters, and the other three are optional parameters, so how do we construct an instance of this class? There are usually two common ways:

public class Computer {
    
    
    private String cpu;//必须
    private String ram;//必须
    private int usbCount;//可选
    private String keyboard;//可选
    private String display;//可选
}

First: Folding the constructor pattern (telescoping constructor pattern), which we often use, as shown in the following code

public class Computer {
    
    
     ...
    public Computer(String cpu, String ram) {
    
    
        this(cpu, ram, 0);
    }
    public Computer(String cpu, String ram, int usbCount) {
    
    
        this(cpu, ram, usbCount, "罗技键盘");
    }
    public Computer(String cpu, String ram, int usbCount, String keyboard) {
    
    
        this(cpu, ram, usbCount, keyboard, "三星显示器");
    }
    public Computer(String cpu, String ram, int usbCount, String keyboard, String display) {
    
    
        this.cpu = cpu;
        this.ram = ram;
        this.usbCount = usbCount;
        this.keyboard = keyboard;
        this.display = display;
    }
}

The second: Javabean mode, as shown below

public class Computer {
    
    
        ...

    public String getCpu() {
    
    
        return cpu;
    }
    public void setCpu(String cpu) {
    
    
        this.cpu = cpu;
    }
    public String getRam() {
    
    
        return ram;
    }
    public void setRam(String ram) {
    
    
        this.ram = ram;
    }
    public int getUsbCount() {
    
    
        return usbCount;
    }
...
}

So what are the disadvantages of these two methods?

The first one is mainly inconvenient to use and read. You can imagine that when you want to call the constructor of a class, you must first decide which one to use, and then there are a bunch of parameters. If the types of these parameters are many and the same, you have to figure out the parameters of these parameters. The meaning is easily passed on

In the second way, the state of the object is prone to change during the construction process, causing errors. Because the properties in that class are set step by step, it is prone to errors.

Implement builder mode

  1. Create a static internal class Builder in the Computer, and then copy the parameters in the Computer to the Builder class
  2. Create a private constructor in Computer, the parameter is of type Builder
  3. Create a public constructor in the Builder, the parameters are those required in the Computer, cpu and ram
  4. Create a setting function in the Builder, assign values ​​to those optional parameters in the Computer, and the return value is an instance of the Builder type
  5. Create a build() method in Builder, build an instance of Computer in it and return

Code

public class Computer {
    
    
    private final String cpu;//必须
    private final String ram;//必须
    private final int usbCount;//可选
    private final String keyboard;//可选
    private final String display;//可选

    private Computer(Builder builder){
    
    
        this.cpu=builder.cpu;
        this.ram=builder.ram;
        this.usbCount=builder.usbCount;
        this.keyboard=builder.keyboard;
        this.display=builder.display;
    }
    public static class Builder{
    
    
        private String cpu;//必须
        private String ram;//必须
        private int usbCount;//可选
        private String keyboard;//可选
        private String display;//可选

        public Builder(String cup,String ram){
    
    
            this.cpu=cup;
            this.ram=ram;
        }

        public Builder setUsbCount(int usbCount) {
    
    
            this.usbCount = usbCount;
            return this;
        }
        public Builder setKeyboard(String keyboard) {
    
    
            this.keyboard = keyboard;
            return this;
        }
        public Builder setDisplay(String display) {
    
    
            this.display = display;
            return this;
        }        
        public Computer build(){
    
    
            return new Computer(this);
        }
    }
  //省略getter方法
}s

use

Use chain call on the client to build the object step by step.

Computer computer=new Computer.Builder("因特尔","三星")
                .setDisplay("三星24寸")
                .setKeyboard("罗技")
                .setUsbCount(2)
                .build();

The above content is a simplified way of using Builder in Java. The classic Builder mode (introduced above) is somewhat different from it. It omits the role of director, and hands the construction algorithm to the client. Secondly, it writes the builder into the product class to be built, and finally uses chained calls.

Guess you like

Origin blog.csdn.net/saienenen/article/details/111668146