设计模式之Builder模式

416 阅读3分钟

Builder模式

  1. 对外部隐藏内部实现细节
  2. 分离部件和组装过程
  3. 自由扩展部件和构造过程
  4. 降低解耦,分工明确

适应场景

  1. 相同的方法,不同的执行顺序,产生不同的事件结果
  2. 多个部件和零件,都可以装配到一个对象中,但产生的运行结果又不相同时
  3. 产品类非常复杂,或者产品类中的调用顺序不同产生不同的作用
  4. 当初始化一个对象特别复杂,如参数多,且很多参数具有默认值时

UML类图

说明:
  1. 抽象类Builder由ConcreteBuilder子类来实现
  2. Director类含有一个Builder的实例对象,通过construct方法指导Builder控制Product的流程
  3. ConcreteBuilder实现具体的组装工作(new Product),组装流程由Director控制

代码实例实现

计算机的组装过程较为复杂,且组装过程也不是固定的,我们暂且将计算机的组装过程简化为构建主机,设置显示器,设置操作系统三个步骤,通过Director和具体的Builder来构建计算机对象

  • 计算机抽象类,即Product角色

      public abstract class Computer {
    
      protected String mBoard;
      protected String mDisplay;
      protected String mOS;
    
          public Computer() {
          }
    
          //设置cpu
          public void setBoard(String board){
              mBoard = board;
          }
    
          //设置显示
          public void setDisplay(String display){
              mDisplay = display;
          }
    
          //设置操作系统
          public abstract void setOS();
    
          @Override
          public String toString() {
              return "Computer { " +
                      "mBoard='" + mBoard + '\'' +
                      ", mDisplay='" + mDisplay + '\'' +
                      ", mOS='" + mOS + '\'' +
                      '}';
          }
      }
  • 具体的Computer类,即macboook

      public class Macbook extends Computer{
    
          public Macbook() {
          }
    
          @Override
          public void setOS() {
              mOS = "Mac OS X 10.10";
          }
    
      }
  • 抽象Builder类,只提供抽象方法,也不提供组装方法,有Director实现组装

      public abstract class Builder {
          //设置主机
          public abstract void buildBoard(String board);
    
          //设置显示器
          public abstract void buildDisplay(String display);
    
          //设置操作系统
          public abstract void buildOS();
    
          //创建Computer
          public abstract Computer create();
      }
  • MAcbookBuilder,具体的builder类

      public class MacbookBuilder extends Builder {
    
        //实例化,父类容器容纳子类对象
          private Computer mComputer = new Macbook();
    
          @Override
          public void buildBoard(String board) {
              mComputer.setBoard(board);
          }
    
          @Override
          public void buildDisplay(String display) {
              mComputer.setDisplay(display);
          }
    
          @Override
          public void buildOS() {
              mComputer.setOS();
          }
    
          @Override
          public Computer create() {
              return mComputer;
          }
      }
  • Director类,负责构造Computer,通过传入builder对象,负责具体的组装工作

      public class Director {
          Builder mBuilder = null;
    
          public Director(Builder builder) {
              this.mBuilder = builder;
          }
    
          public void construct(String board, String display){
              mBuilder.buildBoard(board);
              mBuilder.buildDisplay(display);
              mBuilder.buildOS();
          }
      }
  • 测试Main

      public class Main {
    
          public static void main(String[] args) {
    
          //Director,通过传入builder对象,可实现builder的自动组装任务
          Director pcDirector = new Director(macbookBuilder);
    
          //封装构建过程,传入具体的零件信息:4核CPU,内存2GB,MAC操作系统
          pcDirector.construct("英特尔主板 酷睿I7CPU", "Retina 显示器");
    
              //构建计算机,输出相关信息
              System.out.println("Computer Info : " + macbookBuilder.create().toString());
    
          }
      }
  • 运行结果

      Computer Info : Computer { mBoard='英特尔主板 酷睿I7CPU', mDisplay='Retina 显示器', mOS='Mac OS X 10.10'}

总结

  1. 抽象出数据原型Computer,其内包含基本的数据组成
  2. 具体的数据原型MacBook,通过继承Computer而来
  3. Builder类实现具体的装配工作,其内部必须要有数据原型对象(原料)用来装配,但是具体装配的前后顺序不是自己能控制的,只是拥有装配的能力
  4. Director指挥Builder实现具体的装配工作,其内部封装了构建复杂的产品对象过程,对外部隐藏构建的细节,控制装配的流程
  5. Builde的派生类Macbookbuilder,用于构建具体的装配对象Macbook(Computer的派生类类)
  6. Director通过指挥Builder,一起将一个复杂的对象构建和表示过程分离,使同样的构建过程可以创建不同的对象

优点

  • 良好的封装性,使用建造者模式可以使客户端不必要知道产品内部组成的细节
  • 建造者独立,容易扩展

缺点

  • 会产生多余的Builder对象以及Director对象,消耗内存

深度拓展

Android源码分析之Builder模式

参考文献:Android源码设计模式解析与实战