定义

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

在软件开发中我们一定遇到一些复杂的对象,它有一系列的成员属性,可能有各种限制,但是对于使用者来说可能并不想关心这些属性的赋值顺序或者内部的赋值流程,所以我们通过创建一个建造者的对象,封装组合过程,返还给客户端的是一个已经建造完毕的完整产品对象,而用户无须关心该对象所包含的属性以及它们的组装方式

类图

建造者模式类图
建造者模式类图

优缺点

优点

  • 封装性,客户端不必知道产品内部组成的细节;
  • 建造者独立,容易扩展;
  • 便于控制细节风险,具体的建造者是独立的,可以对建造过程逐步细化,而不对其他的模块产生任何影响。

缺点

  • 只适用于相似或者同类产品;
  • 如果产品内部发生改变,那么建造者都要修改。

应用

  • 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。
  • 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式。
  • 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。
  • 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时,也可以采用建造者模式封装该对象的创建过程。该种场景只能是一个补偿方法,因为一个对象不容易获得,而在设计阶段竟然没有发觉,而要通过创建者模式柔化创建过程,本身已经违反设计的最初目标。

实现

作为程序员你可能会想拥有一台自己的台式电脑这时候你看到了B站的装机猿可以帮忙组装电脑,你就准备买好配置让他给你装配。

定义一台电脑的属性:

public class Computer {
   private String cpu ;

   private String ssd;

   private String mainBoard ;

   private String memory ;

   private String power;

   private String box;

   private String graphics;
   //省略getter setter
   }

首先定义一个组装电脑接口

public interface Builder {

    void assembleCpu(String cpu);

    void assembleMainBoard(String mainBoard);

    void assembleGraphics(String graphics);

    void assemblePower(String power);

    void assembleBox(String box);

    void assembleMemory(String memory);

    void assembleSsd(String ssd);

    Computer assembleComputer();
}

再定义一个具体的帮你装机的人也就是装机猿:

public class MonkeyBuilder implements Builder {
   private Computer computer = new Computer();

   @Override
   public void assembleCpu(String cpu) {
      this.computer.setCpu(cpu);
   }

   @Override
   public void assembleMainBoard(String mainBoard) {
      this.computer.setMainBoard(mainBoard);
   }

   @Override
   public void assembleGraphics(String graphics) {
      this.computer.setGraphics(graphics);
   }

   @Override
   public void assemblePower(String power) {
      this.computer.setPower(power);
   }

   @Override
   public void assembleBox(String box) {
      this.computer.setBox(box);
   }

   @Override
   public void assembleMemory(String memory) {
      this.computer.setMemory(memory);
   }

   @Override
   public void assembleSsd(String ssd) {
      this.computer.setSsd(ssd);
   }

   @Override
   public Computer assembleComputer() {
      return this.computer;
   }
}

再定义导演类,也就是指定谁类为你组装电脑,这里你就是这个导演角色:

public class Director {
   private final Builder builder;

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

   public Computer createComputer(String cpu, String ssd, String mainBoard, String memory, String graphics, String box,
         String power) {
      this.builder.assembleCpu(cpu);
      this.builder.assembleGraphics(graphics);
      this.builder.assembleMainBoard(mainBoard);
      this.builder.assembleMemory(memory);
      this.builder.assembleSsd(ssd);
      this.builder.assemblePower(power);
      this.builder.assembleBox(box);

      return this.builder.assembleComputer();
   }

}

客户端类:

public class Client {
   public static void main(String[] args) {
      Builder builder = new MonkeyBuilder();
      //你指定装机猿为你装配电脑
      Director director = new Director(builder);
      //指定装机的配件
      Computer computer = director.createComputer("AMD 3900", "三星evo 970", "微星迫击炮B450M", "威刚万紫千红16G", "英伟达2080TI",
            "爱国者月光宝盒", "振华金蝶650W");
      //超级豪华的配置
      System.out.println("电脑具体参数:" + computer);
   }
}

输出:

电脑具体参数:com.chenly.designpattern.builder.Computer@555590[cpu=AMD 3900,ssd=三星evo 970,mainBoard=微星迫击炮B450M,memory=威刚万紫千红16G,power=振华金蝶650W,box=爱国者月光宝盒,graphics=英伟达2080TI]