1. Definition and characteristics of mode
Definition of Builder pattern: it refers to separating 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 decomposes a complex object into several simple objects, and then builds them step by step. It separates change from invariance, that is, the components of the product are invariable, but each part can be flexibly selected.
The main advantages of this mode are as follows:
- Good encapsulation, separation of construction and representation.
- Good expansibility, each specific builder is independent of each other, which is conducive to the decoupling of the system.
- The client does not need to know the details of the internal composition of the product. The builder can gradually refine the creation process without any impact on other modules, so as to control the detail risk.
Its disadvantages are as follows:
- The components of the product must be the same, which limits its scope of use.
- If the internal changes of the product are complex, if the internal changes of the product occur, the builder should also modify them synchronously, and the later maintenance cost is large.
The concerns of builder mode and factory mode are different: Builder mode pays attention to the assembly process of parts, while factory method mode pays more attention to the creation process of parts, but the two can be used together.
2. Structure and implementation of mode
1. Structure of the model
The main roles of the Builder pattern are as follows.
- Product role: it is a complex object containing multiple components, and its components are created by specific builders.
- Abstract Builder: it is an interface that contains abstract methods for creating various sub parts of a product, and usually includes a method getResult() that returns a complex product.
- Concrete Builder: implement the builder interface and complete the specific creation method of each component of complex products.
- 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 the information of specific products.
[example 1] describe the decoration of the living room with the Builder mode.
Analysis: living room decoration is a complex process, which includes wall decoration, TV selection, sofa purchase and layout, etc. The customer told the decoration requirements to the project manager. The project manager directed the decoration workers to decorate step by step, and finally completed the decoration and layout of the whole living room. Therefore, this example is more suitable to be realized with the builder mode.
The living room here is a product, including wall, TV and sofa. Specific decoration workers are specific builders, who are responsible for the layout of decoration and walls, televisions and sofas. The project manager is the commander, who is responsible for directing the decoration workers to carry out the decoration.
In addition, the show() method is provided in the living room class to display the decoration effect drawing (click here to download the picture of the decoration effect drawing). The client program reads the decoration scheme data in the XML configuration file through the object generator class ReadXML (click here to download the XML file), and calls the project manager for decoration. Its class diagram is shown in Figure 2.
package Builder; import java.awt.*; import javax.swing.*; public class ParlourDecorator { public static void main(String[] args) { try { Decorator d; d = (Decorator) ReadXML.getObject(); ProjectManager m = new ProjectManager(d); Parlour p = m.decorate(); p.show(); } catch (Exception e) { System.out.println(e.getMessage()); } } } //Product: living room class Parlour { private String wall; //wall private String TV; //television private String sofa; //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() { JFrame jf = new JFrame("Builder mode test"); Container contentPane = jf.getContentPane(); JPanel p = new JPanel(); JScrollPane sp = new JScrollPane(p); String parlour = wall + TV + sofa; JLabel l = new JLabel(new ImageIcon("src/" + parlour + ".jpg")); p.setLayout(new GridLayout(1, 1)); p.setBorder(BorderFactory.createTitledBorder("a living room")); p.add(l); contentPane.add(sp, BorderLayout.CENTER); jf.pack(); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } } //Abstract Builder: Decoration worker abstract class Decorator { //Create product object protected Parlour product = new Parlour(); public abstract void buildWall(); public abstract void buildTV(); public abstract void buildSofa(); //Return product object public Parlour getResult() { return product; } } //Specific Builder: specific decoration worker 1 class ConcreteDecorator1 extends Decorator { public void buildWall() { product.setWall("w1"); } public void buildTV() { product.setTV("TV1"); } public void buildSofa() { product.setSofa("sf1"); } } //Specific Builder: specific decoration worker 2 class ConcreteDecorator2 extends Decorator { public void buildWall() { product.setWall("w2"); } public void buildTV() { product.setTV("TV2"); } public void buildSofa() { product.setSofa("sf2"); } } //Commander: Project Manager class ProjectManager { private Decorator builder; public ProjectManager(Decorator builder) { this.builder = builder; } //Product construction and assembly method public Parlour decorate() { builder.buildWall(); builder.buildTV(); builder.buildSofa(); return builder.getResult(); } } package Builder; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.File; class ReadXML { public static Object getObject() { try { DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dFactory.newDocumentBuilder(); Document doc; doc = builder.parse(new File("src/Builder/config.xml")); NodeList nl = doc.getElementsByTagName("className"); Node classNode = nl.item(0).getFirstChild(); String cName = "Builder." + classNode.getNodeValue(); System.out.println("New class name:" + cName); Class<?> c = Class.forName(cName); Object obj = c.newInstance(); return obj; } catch (Exception e) { e.printStackTrace(); return null; } } }
The running results of the program are shown in Figure 3.