1. 简介
建造者模式也叫生成器模式。
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
- Product类:实现了模板方法模式,也就是有模板方法和基本方法,对应下面代码中的BenzModel和BMWModel
- Builder: 抽象建造者,对应下面例子中的CarBuilder
- ConcreteBuilder: 具体建造者,实现Builder,返回一个组建好的对象, 对应下面例子中的BenzBuilder和BMWBuilder
- Director: 导演类,负责安排已有模块的顺序,然后告诉Builder开始建造,对应下面例子中经理
2. 代码实现
场景:
公司的经理给你安排了一项任务:设计一个宝马车模型,该模型要求先发动引擎,然后开启,然后鸣笛,然后停车
过了一段时间,你完成了这个任务,结果经理又给你安排一项任务,这次要求设计一个奔驰车模式,该模型要求先发动引擎,然后开启,没有鸣笛,然后停车…
然后反复这个过程,你会发现车的启动顺序的变化是不可预测的,因此不可能单独地设计一个类来满足这种执行顺序,因此需要将这种顺序封装起来,直接告诉建造者,让建造者来建造模型
package designpattern;
import java.util.ArrayList;
/*
* setSequence方法是允许客户自己设置一个顺序,是要先
启动响一下喇叭再跑起来,还是要先响一下喇叭再启动。对于一个具体的模型永远都固定
的,但是对N多个模型就是动态的了。在子类中实现父类的基本方法,run()方法读取
sequence,然后遍历sequence中的字符串,哪个字符串在先,就先执行哪个方法
*/
abstract class CarModel{
//保存各个方法的启动顺序
public ArrayList<String> sequence=new ArrayList<>();
public abstract void start();//启动
public abstract void stop();//停止
public abstract void alarm();//鸣笛
public abstract void engine();//发动引擎
public void run() {//按照顺序执行
for(int i=0;i<sequence.size();i++) {
String action=sequence.get(i);
if(action.equals("start"))
this.start();
else if(action.equals("stop"))
this.stop();
else if(action.equals("alarm"))
this.alarm();
else if(action.equals("engine"))
this.engine();
}
}
}
/*
* 奔驰车模型类
*/
class BenzModel extends CarModel{
@Override
public void start() {
System.out.println("Benz start...");
}
@Override
public void stop() {
System.out.println("Benz stop...");
}
@Override
public void alarm() {
System.out.println("Benz alarm...");
}
@Override
public void engine() {
System.out.println("Benz engine...");
}
}
/*
* 宝马车模型类
*/
class BMWModel extends CarModel{
@Override
public void start() {
System.out.println("BMW start...");
}
@Override
public void stop() {
System.out.println("BMW stop...");
}
@Override
public void alarm() {
System.out.println("BMW alarm...");
}
@Override
public void engine() {
System.out.println("BMW engine...");
}
}
abstract class CarBuilder{
//该方法保存组装顺序
public abstract void setSequence(ArrayList<String> sequence);
//返回根据对应顺序建造的车辆模型
public abstract CarModel getCarModel();
}
/*
* 具体的奔驰车建造类中组合使用了具体的奔驰车模型
*/
class BenzBuilder extends CarBuilder{
BenzModel benz=new BenzModel();
@Override
public void setSequence(ArrayList<String> sequence) {
this.benz.sequence=sequence;
}
@Override
public CarModel getCarModel() {
return this.benz;
}
}
/*
* 具体的宝马车建造类中组合使用了具体的宝马车模型
*/
class BMWBuilder extends CarBuilder{
BMWModel bmw=new BMWModel();
@Override
public void setSequence(ArrayList<String> sequence) {
this.bmw.sequence=sequence;
}
@Override
public CarModel getCarModel() {
return this.bmw;
}
}
/*
导演类起到封装的作用,避免高层模块深入到建造者内部的实现类
*/
class Director{
ArrayList<String> sequence=new ArrayList<>();
BenzBuilder benzBuilder=new BenzBuilder();
BMWBuilder bmwBuilder=new BMWBuilder();
/*
* A类型的奔驰 satrt-stop
*/
public BenzModel getABenzModel() {
this.sequence.clear();
this.sequence.add("start");
this.sequence.add("stop");
this.benzBuilder.setSequence(sequence);
return (BenzModel) this.benzBuilder.getCarModel();
}
/*
* B类型的宝马 satrt-alarm-stop
*/
public BMWModel getABmwModel() {
this.sequence.clear();
this.sequence.add("start");
this.sequence.add("alarm");
this.sequence.add("stop");
this.bmwBuilder.setSequence(sequence);
return (BMWModel) this.bmwBuilder.getCarModel();
}
}
public class BuilderDemo {
public static void main(String[] args) {
Director director=new Director();
director.getABenzModel().run();
director.getABmwModel().run();
}
}
3. 优点和使用场景
优点:
- 封装性:客户端不必知道产品内部组成的细节,如例子中我们就不需要关心每一个具体的模型内部是如何实现的,产生的对象类型就是CarModel
- 建造者独立,易拓展:BenzBuilder和BMWBuilder是相互独立的,对系统的扩展非常有利
使用场景:
- 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式
- 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式
- 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适
建造者模式关注的是零件类型和装配工艺(顺序)