Builder模式
- 对外部隐藏内部实现细节
- 分离部件和组装过程
- 自由扩展部件和构造过程
- 降低解耦,分工明确
适应场景
- 相同的方法,不同的执行顺序,产生不同的事件结果
- 多个部件和零件,都可以装配到一个对象中,但产生的运行结果又不相同时
- 产品类非常复杂,或者产品类中的调用顺序不同产生不同的作用
- 当初始化一个对象特别复杂,如参数多,且很多参数具有默认值时
UML类图
说明:
- 抽象类Builder由ConcreteBuilder子类来实现
- Director类含有一个Builder的实例对象,通过construct方法指导Builder控制Product的流程
- 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'}复制代码
总结
- 抽象出数据原型Computer,其内包含基本的数据组成
- 具体的数据原型MacBook,通过继承Computer而来
- Builder类实现具体的装配工作,其内部必须要有数据原型对象(原料)用来装配,但是具体装配的前后顺序不是自己能控制的,只是拥有装配的能力
- Director指挥Builder实现具体的装配工作,其内部封装了构建复杂的产品对象过程,对外部隐藏构建的细节,控制装配的流程
- Builde的派生类Macbookbuilder,用于构建具体的装配对象Macbook(Computer的派生类类)
- Director通过指挥Builder,一起将一个复杂的对象构建和表示过程分离,使同样的构建过程可以创建不同的对象
优点
- 良好的封装性,使用建造者模式可以使客户端不必要知道产品内部组成的细节
- 建造者独立,容易扩展
缺点
- 会产生多余的Builder对象以及Director对象,消耗内存
深度拓展
参考文献:Android源码设计模式解析与实战