建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

背景

将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示
主要解决在软件系统中,有时候面临着”一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

实现

简化版

  1. 在Computer 中创建一个静态内部类 Builder,然后将Computer 中的参数都复制到Builder类中。
  2. 在Computer中创建一个private的构造函数,参数为Builder类型
  3. 在Builder中创建一个public的构造函数,参数为Computer中必填的那些参数,cpu 和ram。
  4. 在Builder中创建设置函数,对Computer中那些可选参数进行赋值,返回值为Builder类型的实例
  5. 在Builder中创建一个build()方法,在其中构建Computer的实例并返回

传统Builder 模式

image.png
如上图所示,builder模式有4个角色。

  • Product: 最终要生成的对象,例如 Computer实例。
  • Builder: 构建者的抽象基类(有时会使用接口代替)。其定义了构建Product的抽象步骤,其实体类需要实现这些步骤。其会包含一个用来返回最终产品的方法Product getProduct()。
  • ConcreteBuilder: Builder的实现类。
  • Director: 决定如何构建最终产品的算法. 其会包含一个负责组装的方法void Construct(Builder builder), 在这个方法中通过调用builder的方法,就可以设置builder,等设置完成后,就可以通过builder的 getProduct() 方法获得最终的产品。

    代码

    简化版

    1. public class Computer {
    2. private final String cpu;//必须
    3. private final String ram;//必须
    4. private final int usbCount;//可选
    5. private final String keyboard;//可选
    6. private final String display;//可选
    7. private Computer(Builder builder){
    8. this.cpu=builder.cpu;
    9. this.ram=builder.ram;
    10. this.usbCount=builder.usbCount;
    11. this.keyboard=builder.keyboard;
    12. this.display=builder.display;
    13. }
    14. public static class Builder{
    15. private String cpu;//必须
    16. private String ram;//必须
    17. private int usbCount;//可选
    18. private String keyboard;//可选
    19. private String display;//可选
    20. public Builder(String cup,String ram){
    21. this.cpu=cup;
    22. this.ram=ram;
    23. }
    24. public Builder setUsbCount(int usbCount) {
    25. this.usbCount = usbCount;
    26. return this;
    27. }
    28. public Builder setKeyboard(String keyboard) {
    29. this.keyboard = keyboard;
    30. return this;
    31. }
    32. public Builder setDisplay(String display) {
    33. this.display = display;
    34. return this;
    35. }
    36. public Computer build(){
    37. return new Computer(this);
    38. }
    39. }
    40. //省略getter方法
    41. }

    使用

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

    传统Builder 模式

    我们的目标Computer类:

    1. public class Computer {
    2. private String cpu;//必须
    3. private String ram;//必须
    4. private int usbCount;//可选
    5. private String keyboard;//可选
    6. private String display;//可选
    7. public Computer(String cpu, String ram) {
    8. this.cpu = cpu;
    9. this.ram = ram;
    10. }
    11. public void setUsbCount(int usbCount) {
    12. this.usbCount = usbCount;
    13. }
    14. public void setKeyboard(String keyboard) {
    15. this.keyboard = keyboard;
    16. }
    17. public void setDisplay(String display) {
    18. this.display = display;
    19. }
    20. @Override
    21. public String toString() {
    22. return "Computer{" +
    23. "cpu='" + cpu + '\'' +
    24. ", ram='" + ram + '\'' +
    25. ", usbCount=" + usbCount +
    26. ", keyboard='" + keyboard + '\'' +
    27. ", display='" + display + '\'' +
    28. '}';
    29. }
    30. }

    抽象构建者类

    public abstract class ComputerBuilder {
      public abstract void setUsbCount();
      public abstract void setKeyboard();
      public abstract void setDisplay();
    
      public abstract Computer getComputer();
    }
    

    第三步:实体构建者类,我们可以根据要构建的产品种类产生多了实体构建者类,这里我们需要构建两种品牌的电脑,苹果电脑和联想电脑,所以我们生成了两个实体构建者类。

    public class MacComputerBuilder extends ComputerBuilder {
      private Computer computer;
      public MacComputerBuilder(String cpu, String ram) {
          computer = new Computer(cpu, ram);
      }
      @Override
      public void setUsbCount() {
          computer.setUsbCount(2);
      }
      @Override
      public void setKeyboard() {
          computer.setKeyboard("苹果键盘");
      }
      @Override
      public void setDisplay() {
          computer.setDisplay("苹果显示器");
      }
      @Override
      public Computer getComputer() {
          return computer;
      }
    }
    
    public class LenovoComputerBuilder extends ComputerBuilder {
      private Computer computer;
      public LenovoComputerBuilder(String cpu, String ram) {
          computer=new Computer(cpu,ram);
      }
      @Override
      public void setUsbCount() {
          computer.setUsbCount(4);
      }
      @Override
      public void setKeyboard() {
          computer.setKeyboard("联想键盘");
      }
      @Override
      public void setDisplay() {
          computer.setDisplay("联想显示器");
      }
      @Override
      public Computer getComputer() {
          return computer;
      }
    }
    

    指导者类(Director)

    public class ComputerDirector {
      public void makeComputer(ComputerBuilder builder){
          builder.setUsbCount();
          builder.setDisplay();
          builder.setKeyboard();
      }
    }
    

    使用
    首先生成一个director (1),然后生成一个目标builder (2),接着使用director组装builder (3),组装完毕后使用builder创建产品实例 (4)。

    public static void main(String[] args) {
          ComputerDirector director=new ComputerDirector();//1
          ComputerBuilder builder=new MacComputerBuilder("I5处理器","三星125");//2
          director.makeComputer(builder);//3
          Computer macComputer=builder.getComputer();//4
          System.out.println("mac computer:"+macComputer.toString());
    
          ComputerBuilder lenovoBuilder=new LenovoComputerBuilder("I7处理器","海力士222");
          director.makeComputer(lenovoBuilder);
          Computer lenovoComputer=lenovoBuilder.getComputer();
          System.out.println("lenovo computer:"+lenovoComputer.toString());
    }