建造者模式定义与特点
建造者(Builder)模式定义:
指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
该模式的主要优点:
1、各个具体的建造者相互独立,有利于系统的扩展。
2、客户端不必知道产品内部组成的细节,便于控制细节风险。
同样的,主要缺点:
1、产品的组成部分必须相同,这限制了其使用范围。
2、如果产品的内部变化复杂,该模式会增加很多的建造者类。
3、建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。
建造者模式的结构
建造者(Builder)模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成,现在我们来分析其基本结构和实现方法。
主要角色如下。
1、产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个部件。
2、抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法getResult()。
3、具体建造者(Concrete Builder):实现抽象建造者接口,完成复杂产品的各个部件的具体创建方法。
4、指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
建造者(Builder)模式的具体实现
A、抽象的产品角色(Product):
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();
//那模型应该会跑吧,别管是人推的,还是电力驱动,总之要会跑
final public void run() {
//循环一遍,谁在前,就先执行谁
for (int i = 0; i < this.sequence.size(); i++) {
String actionName = this.sequence.get(i);
//如果是start关键字,开启汽车;//如果是stop关键字,停止汽车
if (actionName.equalsIgnoreCase("start")) {
this.start();
} else if (actionName.equalsIgnoreCase("stop")) {
this.stop();
//如果是alarm关键字,喇叭开始叫了;如果是engineboom关键字,引擎开始轰鸣
} else if(actionName.equalsIgnoreCase("alarm")){
this.alarm();
}else if(actionName.equalsIgnoreCase("engine boom")) {
this.engineBoom();
}
}
}
//把传递过来的值传递到类内
final public void setSequence(ArrayList<String> sequence) { this.sequence = sequence; }
}
B1、产品角色(Product):奔驰车模型
public class BenzModel extends CarModel {
@Override
protected void alarm() {
System.out.println("奔驰车的喇叭声音是这个样子的...");
}
@Override
protected void engineBoom() {
System.out.println("奔驰车的引擎是这个声音的...");
}
@Override
protected void start() {
System.out.println("奔驰车跑起来是这个样子的...");
}
@Override
protected void stop() {
System.out.println("奔驰车应该这样停车...");
}
}
B2、产品角色(Product):宝马车模型
public class BMWModel extends CarModel {
@Override
protected void alarm() {
System.out.println("宝马车的喇叭声音是这个样子的...");
}
@Override
protected void engineBoom() {
System.out.println("宝马车的引擎是这个声音的...");
}
@Override
protected void start() {
System.out.println("宝马车跑起来是这个样子的...");
}
@Override
protected void stop() {
System.out.println("宝马车应该这样停车...");
}
}
C、抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口或抽象类,通常还包含一个返回复杂产品的方法getResult(),比如这里的getCarModel()。
public abstract class CarBuilder {
//建造一个模型,你要给我一个顺序要,就是组装顺序
public abstract void setSequence(ArrayList<String> sequence);
//设置完毕顺序后,就可以直接拿到这个车辆模型
public abstract CarModel getCarModel();
}
D1、具体建造者(Concrete Builder):实现抽象建造者接口,完成复杂产品的各个部件的具体创建方法。
public class BenzBuilder extends CarBuilder {
private BenzModel benz = new BenzModel();
@Override
public CarModel getCarModel() {
return this.benz;
}
@Override
public void setSequence(ArrayList<String> sequence) {
this.benz.setSequence(sequence);
}
}
D2、体建造者(Concrete Builder):实现抽象建造者接口,完成复杂产品的各个部件的具体创建方法。
public class BMWBuilder extends CarBuilder {
private BMWModel bmw = new BMWModel();
@Override
public CarModel getCarModel() {
return this.bmw;
}
@Override
public void setSequence(ArrayList<String> sequence) {
this.bmw.setSequence(sequence);
}
}
E、指挥者:调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
public class Director {
private ArrayList<String> sequence = new ArrayList();
private BenzBuilder benzBuilder = new BenzBuilder();
private BMWBuilder bmwBuilder = new BMWBuilder();
/**
* A类型的奔驰车模型,先start,然后stop,其他什么引擎了,喇叭一概没有
*/
public BenzModel getABenzModel() {
//清理场景,这里是一些初级程序员不注意的地方
this.sequence.clear();
//这只ABenzModel的执行顺序
this.sequence.add("start");
this.sequence.add("stop");
//按照顺序返回一个奔驰车
this.benzBuilder.setSequence(this.sequence);
return (BenzModel) this.benzBuilder.getCarModel();
}
/**
* B型号的奔驰车模型,是先发动引擎,然后启动,然后停止,没有喇叭
*/
public BenzModel getBBenzModel() {
this.sequence.clear();
this.sequence.add("engine boom");
this.sequence.add("start");
this.sequence.add("stop");
this.benzBuilder.setSequence(this.sequence);
return (BenzModel) this.benzBuilder.getCarModel();
}
/**
* C型号的宝马车是先按下喇叭(炫耀嘛),然后启动,然后停止
*/
public BMWModel getCBMWModel() {
this.sequence.clear();
this.sequence.add("alarm");
this.sequence.add("start");
this.sequence.add("stop");
this.bmwBuilder.setSequence(this.sequence);
return (BMWModel) this.bmwBuilder.getCarModel();
}
/**
* D类型的宝马车只有一个功能,就是跑,启动起来就跑,永远不停止,牛叉
*/
public BMWModel getDBMWModel() {
this.sequence.clear();
this.sequence.add("start");
this.bmwBuilder.setSequence(this.sequence);
return (BMWModel) this.bmwBuilder.getCarModel();
}
/**
* 这里还可以有很多方法,你可以先停止,然后再启动,或者一直停着不动,静态的嘛
* 导演类嘛,按照什么顺序是导演说了算
*/
}
F、客户端调用
public class CarBuilderClient {
public static void main(String[] args) {
Director director = new Director();
//12辆A类型的奔驰车
for (int i = 0; i < 12; i++) {
director.getABenzModel().run();
}
//12W辆B类型的奔驰车
for (int i = 0; i < 12; i++) {
director.getBBenzModel().run();
}
//12量C类型的宝马车
for (int i = 0; i < 12; i++) {
director.getCBMWModel().run();
}
//12量D类型的宝马车
for (int i = 0; i < 12; i++) {
director.getDBMWModel().run();
}
}
}