实现一个汽车模型,可以由客户任意调整零件顺序
实现类图
1.先定义一个CarModel类,实现汽车的整体模型:
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类型,防止被子类修改
final 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("engine boom")){
this.engineBoom();
}
}
}
//设置步骤过程
final public void setSequence(ArrayList sequence){
this.sequence = sequence;
}
}
2. 分别实现具体的汽车模型-宝马和奔驰
package original;
/**
* Created by Administrator on 2017/3/9/009.
* 实现奔驰车的零件
*/
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("奔驰车的引擎声音是这样的....");
}
}
package original;
/**
* Created by Administrator on 2017/3/9/009.
* 实现宝马车的零件
*/
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("宝马车引擎声是这样的....");
}
}
3. 客户可以根据自己的需求定义零件的顺序:
public class Client {
public static void main(String[] args){
//满足需求,可以由客户调整步骤
BenzModel benz = new BenzModel();
ArrayList<String> sequence = new ArrayList<>();
sequence.add("engine boom");
sequence.add("start");
sequence.add("stop");
benz.setSequence(sequence);
benz.run();
}
}
问题是我们这样做只满足和一个需求,如果出现更多的需求呢?因此,我们要设计一个中新的模式:为每种模型产品模型定义一个建造者,要什么顺序,由建造者来建造。
设计类图:
1. 定义一个父类建造者
/**
* Created by Administrator on 2017/3/9/009.
* 定义一个汽车建造者父类
*/
public abstract class CarBuilder {
//设置零件顺序
public abstract void setSequence(ArrayList<String> sequence);
//获取到汽车模型
public abstract CarModel getCarModel();
}
2. 构建具体的奔驰建造者和宝马建造者
/**
* Created by Administrator on 2017/3/9/009.
* 实现具体的奔驰建造者
*/
public class BenZBuilder extends CarBuilder {
//获取到一个奔驰引用
private BenzModel benz = new BenzModel();
//设置其零件顺序
@Override
public void setSequence(ArrayList<String> sequence) {
this.benz.setSequence(sequence);
}
//返回当前奔驰模型
@Override
public CarModel getCarModel() {
return this.benz;
}
}
public class BMWBuilder extends CarBuilder {
private BMWModel bmw = new BMWModel();
@Override
public void setSequence(ArrayList<String> sequence) {
this.bmw.setSequence(sequence);
}
@Override
public CarModel getCarModel() {
return this.bmw;
}
}
3. 客户再次调用,只要将顺序交给建造者,就可以建造出相应的模型出来
public static void main(String[] args){
//设置零件顺序
ArrayList<String> sequence = new ArrayList<>();
sequence.add("engine boom");
sequence.add("start");
sequence.add("stop");
//创建建造者
BenZBuilder builder = new BenZBuilder();
//将零件顺序传递给建造者
builder.setSequence(sequence);
//根据零件顺序创建出既定的模型
BenzModel benz = (BenzModel) builder.getCarModel();
benz.run();
}
4. 封装建造者,我们建立一个导演对象,指定各个事件的顺序,然后为每种顺序都指定一个代码,以便即可生产出对应的模型。
设计类图
a. 建立导演对象:
public class Director {
//定义顺序列表和建造者
private ArrayList<String> sequence = new ArrayList<>();
private BenZBuilder benZBuilder = new BenZBuilder();
private BMWBuilder bmwBuilder = new BMWBuilder();
//通过建造者实现各种不同类型的汽车模型
public BenzModel getABenZModel(){
this.sequence.clear();
this.sequence.add("start");
this.sequence.add("stop");
this.benZBuilder.setSequence(this.sequence);
return (BenzModel) this.benZBuilder.getCarModel();
}
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();
}
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();
}
public BMWModel getDBMWModel(){
this.sequence.clear();
this.sequence.add("start");
this.bmwBuilder.setSequence(this.sequence);
return (BMWModel) this.bmwBuilder.getCarModel();
}
}
b. 这样我们就可以批量地生产各种不同种类型了,当需要增加类型时,只需在Director中添加即可生产。
public static void main(String[] args){
Director director = new Director();
for (int i = 0; i < 10; i ++){
director.getABenZModel().run();
}
for (int i = 0; i < 10; i ++){
director.getBBenZModel().run();
}
for (int i = 0; i < 10; i ++){
director.getCBMWModel().run();
}
}
建造者模式:将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
1. 通用类图:
2. 角色:
a. Product类:
通常实现了模板方法模式,其中BenzModel和BMWModel就属于产品类。
b. Builder抽象建造者:
规范产品的组建,一般由子类实现,其中CarBuilder就是抽象建造者。
c. ConcreteBuilder具体建造者:
实现抽象类定义的所有方法,并且返回一个组建好的对象,其中BenzBuilder就属于具体建造者。
d. Director导演类:
负责安排已有的模板的顺序,然后告诉Builder开始建造。
3. 建造者模式的优点:
a. 封装性:
使用建造者模式可以使客户端不必知道产品内部组成的细节。
b. 建造者独立,易于扩展。
c. 便于控制细节风险:
由于具体的建造者是独立的,因此对于建造过程逐步细化,而不对其他的模块产生任何影响。
- 建造者的使用场景
a. 相同的方法,不同的执行顺序,产生不同的事件结果。
b. 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同。
c. 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能。