Builder Mode for Crazy Learning Java Design Patterns
1. Mode Type
Builder Pattern is a Creative Pattern
2. Mode Definition
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. Such a design pattern is called Builder Pattern. It also decomposes a complex object into several simple objects and builds them step by step. It will be separated from the immutable, that is, the components of the product are the same, but each part can be chosen flexibly.
3. Introduction to Modes
1. What are the main problems to be solved?
- Solve the problem of too many constructor parameters and optional parameters
- Solve the problem of setting N parameters when initializing an instance of a class
2. Use scenarios
- Consider using the constructor pattern when there are many constructor parameters for a class and some of them are optional.
3. Advantages
- Good encapsulation, separation of build and presentation.
- The scalability is good, and the individual builders are independent of each other, which facilitates the decoupling of the system.
- Clients do not need to know the details of the internal composition of the product, and builders can refine the creation process step by step without affecting other modules to control the risk of details.
4. Disadvantages
- The components of the product must be the same, which limits its range of use.
- If the internal changes of the product are complex, if the internal changes of the product, the builder also needs to synchronize the modifications, and later maintenance costs are higher.
5. The difference between this mode and the factory mode
The Builder and Factory modes have different concerns:
- The builder model focuses on the assembly process of components.
- and Factory Method Mode More attention is paid to the process of creating parts, but they can be used in combination.
4. Structure and implementation of patterns
The Builder model is composed of four elements: product, Abstract builder, concrete builder, commander, etc. Now let's analyze its basic structure and implementation.
1. Structure of patterns
The main roles of the Builder pattern are as follows.
- Product role: It is a complex object with multiple components, each of which is created by a specific builder.
- Builder: It is an interface that contains an abstract method for creating individual parts of a product and usually a method getResult() that returns a complex product.
- Concrete Builder: Implement the Builder interface to complete the specific creation of components of a complex product.
- Director: It invokes the component construction and assembly methods in the builder object to complete the creation of complex objects without involving specific product information in the commander.
2. Traditional implementation of patterns
-
Product role: It is a complex object with multiple components, each of which is created by a specific builder.
package com.gitee.qianpz.builder.pattern.conventional; /** * Product role: It is a complex object with multiple components, each of which is created by a specific builder. * * @author pengzhan.qian * @since 1.0.0 */ public class Product { private String partA; private String partB; private String partC; public String getPartA() { return partA; } public void setPartA(String partA) { this.partA = partA; } public String getPartB() { return partB; } public void setPartB(String partB) { this.partB = partB; } public String getPartC() { return partC; } public void setPartC(String partC) { this.partC = partC; } @Override public String toString() { return "Product{" + "partA='" + partA + '\'' + ", partB='" + partB + '\'' + ", partC='" + partC + '\'' + '}'; }
-
Builder: It is an interface that contains an abstract method for creating individual parts of a product and usually a method getResult() that returns a complex product.
package com.gitee.qianpz.builder.pattern.conventional; /** * Builder: It is an interface that contains an abstract method for creating individual parts of a product and usually a method getResult() that returns a complex product. * * @author pengzhan.qian * @since 1.0.0 */ public abstract class AbstractProductBuilder { /** * Initialize product object */ protected Product product = new Product(); /** * Assembly Part A * * @return */ public abstract void setPartA(); /** * Assembly Part B * * @return */ public abstract void setPartB(); /** * Assembly Part C * * @return */ public abstract void setPartC(); /** * Return the assembled product * * @return */ public Product getResult() { return product; } }
-
Concrete Builder: Implement the Builder interface to complete the specific creation of components of a complex product.
package com.gitee.qianpz.builder.pattern.conventional; /** * Concrete Builder: Implement the Builder interface to complete the specific creation of components of a complex product. * * @author pengzhan.qian * @since 1.0.0 */ public class ConcreteProductBuilderA extends AbstractProductBuilder { @Override public void setPartA() { product.setPartA("Assembly parts A"); } @Override public void setPartB() { product.setPartB("Assembly parts B"); } @Override public void setPartC() { product.setPartC("Assembly parts C"); } } package com.gitee.qianpz.builder.pattern.conventional; /** * Concrete Builder: Implement the Builder interface to complete the specific creation of components of a complex product. * * @author pengzhan.qian * @since 1.0.0 */ public class ConcreteProductBuilderB extends AbstractProductBuilder { @Override public void setPartA() { product.setPartA("Assembly parts A"); } @Override public void setPartB() { product.setPartB("Assembly parts B"); } @Override public void setPartC() { product.setPartC("Assembly parts C"); } }
-
Director: It invokes the component construction and assembly methods in the builder object to complete the creation of complex objects without involving specific product information in the commander.
package com.gitee.qianpz.builder.pattern.conventional; /** * Director: It invokes the component construction and assembly methods in the builder object to complete the creation of complex objects without involving specific product information in the commander. * * @author pengzhan.qian * @since 1.0.0 */ public class Director { private final AbstractProductBuilder abstractProductBuilder; /** * Initialize builder * Who to build * * @param abstractProductBuilder */ public Director(AbstractProductBuilder abstractProductBuilder) { this.abstractProductBuilder = abstractProductBuilder; } /** * Assemble product * * @return */ public Product construct() { abstractProductBuilder.setPartA(); abstractProductBuilder.setPartB(); abstractProductBuilder.setPartC(); return abstractProductBuilder.getResult(); } }
-
Client Call
package com.gitee.qianpz.builder.pattern.conventional; /** * Client * * @author pengzhan.qian * @since 1.0.0 */ public class Client { public static void main(String[] args) { //Specify builder AbstractProductBuilder concreteProductBuilderA = new ConcreteProductBuilderA(); //The commander tells the builder what to do Director director1 = new Director(concreteProductBuilderA); //Builder to assemble Product product1 = director1.construct(); //Product Display System.out.println(product1.toString()); //Specify builder AbstractProductBuilder concreteProductBuilderB = new ConcreteProductBuilderB(); //The commander tells the builder what to do Director director2 = new Director(concreteProductBuilderB); //Builder to assemble Product product2 = director2.construct(); //Product Display System.out.println(product2.toString()); } }
-
Execution results:
Product{partA='A Builder Assembly Part A', partB='A Builder Assembly Part B', partC='A Builder Assembly Part C'} Product{partA='B Builder Assembly Part A', partB='B Builder Assembly Part B', partC='B Builder Assembly Part C'}
-
UML diagrams
3. Chain implementation of patterns
-
Specific products
package com.gitee.qianpz.builder.pattern.chain; /** * Specific products * * @author pengzhan.qian * @since 1.0.0 */ public class Computer { /** * Computer Name */ private String name; /** * Computer CPU 4 Core or 8 Core */ private String cpu; /** * USB Number of interfaces */ private Integer usbCount; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCpu() { return cpu; } public void setCpu(String cpu) { this.cpu = cpu; } public Integer getUsbCount() { return usbCount; } public void setUsbCount(Integer usbCount) { this.usbCount = usbCount; } @Override public String toString() { return "Computer{" + "name='" + name + '\'' + ", cpu='" + cpu + '\'' + ", usbCount=" + usbCount + '}'; } }
-
Builder
package com.gitee.qianpz.builder.pattern.chain; /** * @author pengzhan.qian * @since 1.0.0 */ public class ComputerBuilder { private Computer computer = new Computer(); /** * Easy chain return * * @return */ public static ComputerBuilder build() { return new ComputerBuilder(); } /** * Build a computer name * * @param name * @return */ public ComputerBuilder addName(String name) { computer.setName(name); return this; } /** * Build computer CPU * * @param cpu * @return */ public ComputerBuilder addCpu(String cpu) { computer.setCpu(cpu); return this; } /** * Number of computer USB interfaces built * * @param usbCount * @return */ public ComputerBuilder addUsbCount(Integer usbCount) { computer.setUsbCount(usbCount); return this; } /** * Product initialization builder * * @return */ public Computer builder() { return computer; } }
-
Client
package com.gitee.qianpz.builder.pattern.chain; /** * Client * * @author pengzhan.qian * @since 1.0.0 */ public class Client { public static void main(String[] args) { ComputerBuilder computerBuilder = new ComputerBuilder() .addName("Apple Mac Pro") .addCpu("Intel 8 nucleus ") .addUsbCount(3); Computer computer = computerBuilder.builder(); System.out.println(computer.toString()); //This pattern is our common use of StringBuilder using the chain builder pattern ComputerBuilder computerBuilder1 = ComputerBuilder.build() .addName("Apple Mac Pro") .addCpu("Intel 8 nucleus ") .addUsbCount(3); Computer computer1 = computerBuilder1.builder(); System.out.println(computer1.toString()); //This is how lombok's @builder annotation is used Computer computer2 = ComputerBuilder.build() .addName("association Lenov") .addCpu("Intel 4 nucleus ") .addUsbCount(5).builder(); System.out.println(computer2.toString()); } } Execution results: Computer{name='Apple Mac Pro', cpu='Intel 8 nucleus ', usbCount=3} Computer{name='Apple Mac Pro', cpu='Intel 8 nucleus ', usbCount=3} Computer{name='association Lenov', cpu='Intel 4 nucleus ', usbCount=5}