Quick Start with Common Design Patterns - Producer

Producer Builder

The builder pattern (Builder) uses multiple simple objects to build a complex object step by step.

Applicable scene

In software development, there are a large number of complex objects, which have a series of member variables and nested objects that require cumbersome initialization. And in these complex objects, there may also be some restrictions, such as:

  1. A complex object cannot be used as a complete product if certain properties are not assigned.
  2. Some attributes must be assigned in a certain order. Before one attribute is assigned, another attribute may not be assigned.

In order to solve these complex initialization tasks, a generator is designed for initialization and assembly, and a supervisor is used to specify the flow and configuration of different production lines.

core role

  1. Builder: A method of abstracting the steps in the production of a product.
  2. Concrete Builders: Different concrete implementations of product production step methods.
  3. Products (Products): The final generated object. It contains various components, and the generator is used to assemble the components into the product to produce a specific product.
  4. Director: The class defines the order in which the construction steps are invoked so that you can create and reuse specific product configurations.

scene simulation

If we need to generate a computer (product) and its configuration manual (product) to the user, assuming that the components of a computer (product) are composed of CPU, motherboard, power supply, memory, and hard disk, the properties of which are shown in the following figure:

component name CPU motherboard power supply Memory hard disk
Component Properties CPU type motherboard size power wattage Memory model Memory Capacity HDD type Hard drive capacity
attribute value Intel / AMD ITX / MATX / ATX 500~2000 DDR4 / DDR5 2~16 Mechanical HDD / SSD 1024~16384 512~4096

Among them, the entire generator structure can be represented by the following table:

level application layer middle layer - supervisor middle layer - generator Bottom-Product Bottom-component
builder interface
kind client Supervisor computer generator Computers (Products) CPU, motherboard, power supply, memory, hard disk
PC Specification Generator Computer Configuration Instructions (Products)

Implementation process

  1. Clearly define members to ensure they can manufacture all forms of products.

    明确生成一台电脑和一本电脑配置说明需要设置好CPU、主板、电源、内存、硬盘这几个属性。
    
  2. Define the product (computer, computer description) and components (CPU, motherboard, power supply, memory, hard drive).

    product

    // 电脑
    public class Computer {
          
          
        private int price;
        private Cpu cpu;
        private Mainboard mainboard;
        private PowerSupply powerSupply;
        private Memory memory;
        private HardDisk hardDisk;
    	// 记得写参数构造函数
        public Computer(int price, Cpu cpu, Mainboard mainboard, PowerSupply powerSupply, Memory memory, HardDisk hardDisk) {
          
          
            this.price = price;
            this.cpu = cpu;
            this.mainboard = mainboard;
            this.powerSupply = powerSupply;
            this.memory = memory;
            this.hardDisk = hardDisk;
        }
    
        // 构造函数整体set,这里只提供get函数
        public int getPrice() {
          
          
            return price;
        }
    
        public Cpu getCpu() {
          
          
            return cpu;
        }
    
        public Mainboard getMainboard() {
          
          
            return mainboard;
        }
    
        public PowerSupply getPowerSupply() {
          
          
            return powerSupply;
        }
    
        public Memory getMemory() {
          
          
            return memory;
        }
    
        public HardDisk getHardDisk() {
          
          
            return hardDisk;
        }
    
    }
    
    
    // 电脑说明书
    public class ComputerManual {
          
          
        private int price;
        private Cpu cpu;
        private Mainboard mainboard;
        private PowerSupply powerSupply;
        private Memory memory;
        private HardDisk hardDisk;
    	// 记得写参数构造函数
        public ComputerManual(int price, Cpu cpu, Mainboard mainboard, PowerSupply powerSupply, Memory memory, HardDisk hardDisk) {
          
          
            this.price = price;
            this.cpu = cpu;
            this.mainboard = mainboard;
            this.powerSupply = powerSupply;
            this.memory = memory;
            this.hardDisk = hardDisk;
        }
    
        // 构造函数整体set,这里只提供get函数
        public int getPrice() {
          
          
            return price;
        }
    
        public Cpu getCpu() {
          
          
            return cpu;
        }
    
        public Mainboard getMainboard() {
          
          
            return mainboard;
        }
    
        public PowerSupply getPowerSupply() {
          
          
            return powerSupply;
        }
    
        public Memory getMemory() {
          
          
            return memory;
        }
    
        public HardDisk getHardDisk() {
          
          
            return hardDisk;
        }
    
        @Override
        public String toString() {
          
          
            return "ComputerManual{" +
                    "price=" + price +
                    ", cpu=" + cpu +
                    ", mainboard=" + mainboard +
                    ", powerSupply=" + powerSupply.toString() +
                    ", memory=" + memory.toString() +
                    ", hardDisk=" + hardDisk.toString() +
                    '}';
        }
    }
    

    components

    // CPU
    public enum Cpu {
          
          
        Intel,AMD
    }
    
    // 主板
    public enum Mainboard {
          
          
        ITX, MATX, ATX
    }
    
    // 电源
    public class PowerSupply {
          
          
        private int power;
    
        public PowerSupply(int power) {
          
          
            if (power >= 500 && power <= 2000){
          
          
                this.power = power;
            }else {
          
          
                System.out.println(String.format("%s w is invalid power!"));
            }
        }
    
        public int getPower() {
          
          
            return power;
        }
    
        @Override
        public String toString() {
          
          
            return "PowerSupply{" +
                    "power=" + power +
                    '}';
        }
    }
    
    // 内存
    public enum MemoryType {
          
          
        DDR4, DDR5
    }
    // and
    public class Memory {
          
          
        private MemoryType memoryType;
        private int capacity;
    
        public Memory(MemoryType memoryType, int capacity) {
          
          
            this.memoryType = memoryType;
            if (capacity >= 2 && capacity <= 16) {
          
          
                this.capacity = capacity;
            } else {
          
          
                System.out.println(String.format("%s g is invalid memory capacity!"));
            }
        }
    
        public MemoryType getMemoryType() {
          
          
            return memoryType;
        }
    
        public int getCapacity() {
          
          
            return capacity;
        }
    
        @Override
        public String toString() {
          
          
            return "Memory{" +
                    "memoryType=" + memoryType +
                    ", capacity=" + capacity +
                    '}';
        }
    }
    
    // 硬盘
    public enum HardDiskType {
          
          
        Mechanical, Solid
    }
    // and
    public class HardDisk {
          
          
        private HardDiskType hardDiskType;
        private int capacity;
    
        public HardDisk(HardDiskType hardDiskType, int capacity) {
          
          
            this.hardDiskType = hardDiskType;
            if (hardDiskType == HardDiskType.Mechanical) {
          
          
                if (capacity >= 1024 && capacity <= 16384) {
          
          
                    this.capacity = capacity;
                } else {
          
          
                    System.out.println(String.format("%s g is invalid mechanical hard disk capacity!"));
                }
            } else if (hardDiskType == HardDiskType.Solid) {
          
          
                if (capacity >= 512 && capacity <= 4096) {
          
          
                    this.capacity = capacity;
                } else {
          
          
                    System.out.println(String.format("%s g is invalid solid hard disk capacity!"));
                }
            }
        }
    
        public HardDiskType getHardDiskType() {
          
          
            return hardDiskType;
        }
    
        public int getCapacity() {
          
          
            return capacity;
        }
    
        @Override
        public String toString() {
          
          
            return "HardDisk{" +
                    "hardDiskType=" + hardDiskType +
                    ", capacity=" + capacity +
                    '}';
        }
    }
    
  3. Declare these steps in the base builder interface.

    public interface Builder {
          
          
        // 只设计必要set函数,不设计输出完整产品的函数
        void setCpu(Cpu cpu);
    
        void setMainboard(Mainboard mainboard);
    
        void setPowerSupply(PowerSupply powerSupply);
    
        void setMemory(Memory memory);
    
        void setHardDisk(HardDisk hardDisk);
    }
    
  4. Create concrete builder classes for each form of product and implement their construction steps. PS: Don't forget to implement the method of obtaining the construction result object, that is, getComputer() and getComputerManual() below . You can't declare the method in the builder interface, because the products constructed by different builders may not have a common interface (Computer and ComputerManual), so you don't know the type of object that the method returns.

    // 电脑生成器
    public class ComputerBuilder implements Builder {
          
          
        private int price;
        private Cpu cpu;
        private Mainboard mainboard;
        private PowerSupply powerSupply;
        private Memory memory;
        private HardDisk hardDisk;
    
        public void setPrice(int price) {
          
          
            this.price = price;
        }
    
        @Override
        public void setCpu(Cpu cpu) {
          
          
            this.cpu = cpu;
        }
    
        @Override
        public void setMainboard(Mainboard mainboard) {
          
          
            this.mainboard = mainboard;
        }
    
        @Override
        public void setPowerSupply(PowerSupply powerSupply) {
          
          
            this.powerSupply = powerSupply;
        }
    
        @Override
        public void setMemory(Memory memory) {
          
          
            this.memory = memory;
        }
    
        @Override
        public void setHardDisk(HardDisk hardDisk) {
          
          
            this.hardDisk = hardDisk;
        }
    	// 记得添加获取构造结果对象的方法
        public Computer getComputer() {
          
          
            return new Computer(price, cpu, mainboard, powerSupply, memory, hardDisk);
        }
    }
    
    // 电脑说明书
    public class ComputerManualBuilder implements Builder {
          
          
        private int price;
        private Cpu cpu;
        private Mainboard mainboard;
        private PowerSupply powerSupply;
        private Memory memory;
        private HardDisk hardDisk;
    
        public void setPrice(int price) {
          
          
            this.price = price;
        }
    
        @Override
        public void setCpu(Cpu cpu) {
          
          
            this.cpu = cpu;
        }
    
        @Override
        public void setMainboard(Mainboard mainboard) {
          
          
            this.mainboard = mainboard;
        }
    
        @Override
        public void setPowerSupply(PowerSupply powerSupply) {
          
          
            this.powerSupply = powerSupply;
        }
    
        @Override
        public void setMemory(Memory memory) {
          
          
            this.memory = memory;
        }
    
        @Override
        public void setHardDisk(HardDisk hardDisk) {
          
          
            this.hardDisk = hardDisk;
        }
    	// 记得添加获取构造结果对象的方法
        public ComputerManual getComputerManual() {
          
          
            return new ComputerManual(price, cpu, mainboard, powerSupply, memory, hardDisk);
        }
    }
    
  5. Consider creating a supervisor class. It can use the same builder object to encapsulate multiple ways of constructing a product (designed here to produce both high-performance and low-end computers).

    public class Director {
          
          
        // 主管负责设计好参数
        public void getHighPerformanceComputers(Builder builder) {
          
          
            builder.setCpu(Cpu.Intel);
            builder.setMainboard(Mainboard.MATX);
            builder.setPowerSupply(new PowerSupply(2000));
            builder.setMemory(new Memory(MemoryType.DDR5, 16));
            builder.setHardDisk(new HardDisk(HardDiskType.Solid, 4096));
        }
    
        public void getLowPerformanceComputers(Builder builder) {
          
          
            builder.setCpu(Cpu.Intel);
            builder.setMainboard(Mainboard.ITX);
            builder.setPowerSupply(new PowerSupply(500));
            builder.setMemory(new Memory(MemoryType.DDR4, 2));
            builder.setHardDisk(new HardDisk(HardDiskType.Mechanical, 1024));
        }
    }
    
  6. Client code creates both generator and supervisor objects. Before construction can begin, the client must pass the builder object to the supervisor object. Typically, the client only needs to call the supervisor class constructor once. The supervisor class uses the builder object for all subsequent manufacturing tasks. There is another way, and that is that the client can pass the generator object directly to the manufacture method of the supervisor class.

    public class Application {
          
          
        public static void main(String[] args) {
          
          
            Director director = new Director();
    
            // 创建电脑生成器
            ComputerBuilder computerBuilder = new ComputerBuilder();
            ComputerManualBuilder computerManualBuilder = new ComputerManualBuilder();
    
            // 主管设置生成器参数
            director.getHighPerformanceComputers(computerBuilder);
            director.getHighPerformanceComputers(computerManualBuilder);
    
            // 从配置好的生成器中获取产品
            Computer computer = computerBuilder.getComputer();
            ComputerManual computerManual = computerManualBuilder.getComputerManual();
            System.out.println("The Computer is:" + computerManual.toString());
        }
    }
    
  7. Only if all products conform to the same interface, the result of the construction can be obtained directly through the supervisor class. Otherwise, the client should obtain the construction result through the generator.

Caution

  1. In components and products, a parameter constructor is generally written to facilitate the filling and configuration of supervisor classes and generators.
  2. Only the necessary set functions are designed in the Builder interface, and functions that output complete products are not designed (because the return classes are not uniform)
  3. Continuing from the last one, remember to write a function to obtain the product at the end of the generator that implements the Builder interface.

Guess you like

Origin blog.csdn.net/qq_42078712/article/details/130291369