建造者模式(Builder Patter)
概述
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式又称为生成器模式。
规范产品的组建,一般由子类实现。
实现接口定义的所有方法,并返回一个组建好的对象。
负责安排已有模块的顺序,然后告诉Builder开始建造。
使用场景
- 相同的方法,不同的执行顺序,产生不同的事件后果时,可以采用建造者模式
- 多个部件或零件,都可以装配到一个对象中,但运行结果又不相同时,可以使用建造者模式。
- 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适。
- 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时,也可以采用建造者模式封装该对象的创建过程。
举个栗子
现在有如下场景:有一项业务是制作奔驰和宝马的汽车模型,要求模型有启动,停止,鸣笛,引擎有轰鸣声等四项功能,并且功能顺序都由客户来控制。客户要什么顺序的模型就得马上生产什么顺序的模型,而且还得是批量生产。
提供以下四种模型:
奔驰A模型,先启动,后停止,没有引擎轰隆和喇叭
奔驰B模型,先有引擎声,再启动,后停止
宝马A模型,先鸣笛,再启动,后停止
宝马B模型,直接启动
A客户需求:要3辆A型宝马车
B客户需求:要2辆B型奔驰车
我们需要:传入一个模型的顺序,就能直接返回一个汽车模型对象。
1,创建Product类,基类CarModel,BenzModel和BMWModel继承之。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
public abstract class CarModel { private ArrayList<String> sequence = new ArrayList<>();
protected abstract void start();
protected abstract void stop();
protected abstract void alarm();
protected abstract void engineBoom();
public void run() { for (int i = 0; i < this.sequence.size(); i++) { String actionName = this.sequence.get(i); if (actionName.equalsIgnoreCase("start")) { this.start(); } else if (actionName.equalsIgnoreCase("stop")) { this.stop(); } else if (actionName.equalsIgnoreCase("alarm")) { this.alarm(); } else if (actionName.equalsIgnoreCase("engineBoom")) { this.engineBoom(); } } }
public void setSequence(ArrayList<String> sequence) { this.sequence = sequence; }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
public class BenzModel extends CarModel{
@Override protected void start() { System.out.println("奔驰车跑了..."); }
@Override protected void stop() { System.out.println("奔驰车停了..."); }
@Override protected void alarm() { System.out.println("奔驰车鸣笛了..."); }
@Override protected void engineBoom() { System.out.println("奔驰车引擎轰隆了..."); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class BMWModel extends CarModel{
@Override protected void start() { System.out.println("宝马车跑了..."); }
@Override protected void stop() { System.out.println("宝马车停了..."); }
@Override protected void alarm() { System.out.println("宝马车鸣笛了..."); }
@Override protected void engineBoom() { System.out.println("宝马车引擎轰隆了..."); }
}
|
- 创建建造汽车的规范CarBuilder接口,要求传入一个顺序,设置后直接返回一个模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public interface CarBuilder {
void setSequence(ArrayList<String> sequence);
CarModel getCarModel(); }
|
- 创建具体建造者类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
public class BenzBuilder implements CarBuilder { private BenzModel benzModel = new BenzModel(); @Override public void setSequence(ArrayList<String> sequence) { this.benzModel.setSequence(sequence); } @Override public CarModel getCarModel() { return benzModel; }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public class BMWBuilder implements CarBuilder{
private BMWModel bmwModer = new BMWModel(); @Override public void setSequence(ArrayList<String> sequence) { this.bmwModer.setSequence(sequence); }
@Override public CarModel getCarModel() { return bmwModer; }
}
|
- 创建导演类Director,生产各个型号的车
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
public class Director { private ArrayList<String> sequence = new ArrayList<>();
BenzBuilder benzBuilder = new BenzBuilder(); BMWBuilder bmwBuilder = new BMWBuilder();
public BenzModel getBenzAModel(){ this.sequence.clear(); this.sequence.add("start"); this.sequence.add("stop"); benzBuilder.setSequence(sequence); CarModel benzCarModel = benzBuilder.getCarModel(); return (BenzModel) benzCarModel; }
public BenzModel getBenzBModel(){ this.sequence.clear(); this.sequence.add("engineBoom"); this.sequence.add("start"); this.sequence.add("stop"); benzBuilder.setSequence(sequence); CarModel benzCarModel = benzBuilder.getCarModel(); return (BenzModel) benzCarModel; }
public BMWModel getBMWAModel(){ this.sequence.clear(); this.sequence.add("alarm"); this.sequence.add("start"); this.sequence.add("stop"); bmwBuilder.setSequence(sequence); CarModel bmwCarModel = bmwBuilder.getCarModel(); return (BMWModel) bmwCarModel; }
public BMWModel getBMWBModel(){ this.sequence.clear(); this.sequence.add("start"); bmwBuilder.setSequence(sequence); CarModel bmwCarModel = bmwBuilder.getCarModel(); return (BMWModel) bmwCarModel; } }
|
- 最后是客户端调用Client类,根据需求,批量生产所需型号的车辆
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
public class Client { public static void main(String[] args) {
Director director = new Director(); for (int i = 0; i < 3; i++) { BMWModel bmwaModel = director.getBMWAModel(); bmwaModel.run(); System.out.println("---"); } System.out.println("------------"); for (int i = 0; i < 2; i++) { BenzModel benzBModel = director.getBenzBModel(); benzBModel.run(); System.out.println("---"); } } }
|
- 运行的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 宝马车鸣笛了... 宝马车跑了... 宝马车停了... --- 宝马车鸣笛了... 宝马车跑了... 宝马车停了... --- 宝马车鸣笛了... 宝马车跑了... 宝马车停了... --- ------------ 奔驰车引擎轰隆了... 奔驰车跑了... 奔驰车停了... --- 奔驰车引擎轰隆了... 奔驰车跑了... 奔驰车停了... ---
|
- 完毕
建造者模式的优点
- 封装性好,不需要关心建造者内部的实现细节
- 建造者独立,容易扩展
- 便于控制细节风险
建造者模式与工厂设计模式的区别
- 建造者模式最主要的功能是调用方法的顺序安排,通俗的就是零件的装配,顺序不同 产生的对象不同
- 工厂设计模式重点是创建,创建零件是它的主要职责,组装顺序则不是它所关心的。