生成器模式
生成器模式结构
- 抽象产品类 -->(可以有,但没必要)
- 具体产品类
- 抽象生成器 -->(规定了生产产品的必要步骤)
- 具体生成器 -->(包含生产一个产品必须的所有具体步骤和细节 )
- 主管类 -->(“操控”生成器生产具体产品)
生成器模式特点
- 想要创建的一系列的对象,这些对象首先初始化比较复杂和繁琐,其次制造过程很相似仅仅有细节上的差异的时候,可以考虑使用生成器模式(下面会有举例说明)。
- 生成器模式中的“抽象/具体生成器”,很容易类比为工厂模式中的“抽象/具体工厂”。但是他们的区别是显著的:“具体工厂”会直接产出具体产品(对象),而“具体生成器”并不负责生产具体产品(对象)的过程。具体可以看下面的代码和总结。
- 生成器模式的目的不是生产同一系列的产品。由不同生成器生成的最终具体产品不一定要属于同一接口或抽象类(因此抽象产品类不是必须的)。
讲个故事
话接上回,主要讲到逆丰快递公司使用抽象工厂造飞机、造汽车。所谓造化弄人天妒英才,老板这次玩脱了。由于成本太高而收益有限,逆丰快递不得不砍掉飞机业务,从此专注造汽车和陆上运输。所以今天我只能说说造汽车的事啦(有点遗憾,因为造飞机我也会)。
说到造汽车,首先,要确定汽车有哪些组成部分。车轮、方向盘、油门这些肯定必须的,还有一些细节视车的种类而定,比如有没有离合器?柴油发动机还是汽油发动机?有没有车载导航?有没有车顶(比如我家的帕加尼风之子和保时捷911就没有车顶)等等,可以看到造一辆车要素还是比较多的,具体步骤当然也会比较繁琐。
不多说开始造车。按照先前的套路,应该是这样的一个步骤:
有问题吗?大问题倒也没有,也就代码冗余丑陋点,构造函数庞大繁琐点,调用麻烦点,无用参数过多了点。。。
有更好的解决方案吗?当然有,比如生成器模式如下,源码附在文尾。
抽象和具体产品类:
/**
* 抽象产品类
* 可以有,但没必要。因为生成器模式并非只能生产同一系列的产品。
*/
public abstract class Car {
public String carType;
abstract void info();
}
/**
* 具体产品1:保时捷(其实就是一个POJO)
*/
public class Posche extends Car {
// 轮胎个数
private Integer wheel;
// 方向盘个数
private Integer steering;
// 油门个数
private Integer acclerator;
// 离合器个数
private Integer clutch;
// 柴油发动机
private String dieselEngine;
// 汽油发动机
private String gasolineEngine;
// 车载导航
private String navigator;
// 车顶棚
private String top;
// (篇幅原因这里省略各属性的setter/getter方法)
// ......
@Override
public void info() {
String desc = "这是一辆" + carType + ":\n" +
wheel + "个车轮\n" +
steering + "个方向盘\n" +
acclerator + "个油门\n" +
clutch + "个离合器\n" +
"柴油发动机:" + dieselEngine + "\n" +
"汽油发动机:" + gasolineEngine + "\n" +
"车载导航:" + navigator + "\n" +
"车顶棚:" + top + "\n";
System.out.println(desc);
}
}
/**
* 具体产品2:五菱宏光(其实就是一个POJO)
*/
public class Wuling extends Car {
// 轮胎个数
private Integer wheel;
// 方向盘个数
private Integer steering;
// 油门个数
private Integer acclerator;
// 离合器个数
private Integer clutch;
// 柴油发动机
private String dieselEngine;
// 汽油发动机
private String gasolineEngine;
// 车载导航
private String navigator;
// 车顶棚
private String top;
// (篇幅原因这里省略各属性的setter/getter方法)
// ......
@Override
public void info() {
String desc = "这是一辆" + carType + ":\n" +
wheel + "个车轮\n" +
steering + "个方向盘\n" +
acclerator + "个油门\n" +
clutch + "个离合器\n" +
"柴油发动机:" + dieselEngine + "\n" +
"汽油发动机:" + gasolineEngine + "\n" +
"车载导航:" + navigator + "\n" +
"车顶棚:" + top + "\n";
System.out.println(desc);
}
抽象和具体生成器类:
/**
* 具体生成器类1:保时捷生成器
*/
public class PoscheBuilder implements Builder {
private Posche posche = new Posche();
@Override
public void installSteering(Integer steering) {
posche.setSteering(steering);
}
@Override
public void installWheel(Integer wheel) {
posche.setWheel(wheel);
}
@Override
public void installAccelerator(Integer accelerator) {
posche.setAcclerator(accelerator);
}
@Override
public void installClutch(Integer clutch) {
posche.setClutch(clutch);
}
@Override
public void installDieselEngine(String dieselEngine) {
posche.setDieselEngine(dieselEngine);
}
@Override
public void installGasolineEngine(String gasolineEngine) {
posche.setGasolineEngine(gasolineEngine);
}
@Override
public void installNavigator(String navigator) {
posche.setNavigator(navigator);
}
@Override
public void installTop(String top) {
posche.setTop(top);
}
@Override
public Car getCar() {
posche.carType = "保时捷";
return this.posche;
}
}
/**
* 具体生成器类2:五菱宏光生成器
*/
public class WulingBuilder implements Builder {
private Wuling wuling = new Wuling();
@Override
public void installSteering(Integer steering) {
wuling.setSteering(steering);
}
@Override
public void installWheel(Integer wheel) {
wuling.setWheel(wheel);
}
@Override
public void installAccelerator(Integer accelerator) {
wuling.setAcclerator(accelerator);
}
@Override
public void installClutch(Integer clutch) {
wuling.setClutch(clutch);
}
@Override
public void installDieselEngine(String dieselEngine) {
wuling.setDieselEngine(dieselEngine);
}
@Override
public void installGasolineEngine(String gasolineEngine) {
wuling.setGasolineEngine(gasolineEngine);
}
@Override
public void installNavigator(String navigator) {
wuling.setNavigator(navigator);
}
@Override
public void installTop(String top) {
wuling.setTop(top);
}
@Override
public Car getCar() {
wuling.carType = "五菱宏光";
return this.wuling;
}
}
主管类(核心部分):
/**
* 主管类
* 主管类可以理解成是生成器的指挥者,指挥生成器调用某些步骤,以及调整不同步骤的顺序等
*/
public class CarDirector {
// 生产保时捷的详细步骤和顺序
public void producePosche(Builder builder){
builder.installWheel(4);
builder.installSteering(1);
builder.installAccelerator(1);
builder.installGasolineEngine("高端汽油发动机");
builder.installNavigator("高端车载导航");
}
// 生产五菱宏光的详细步骤和顺序
public void produceWuling(Builder builder){
builder.installWheel(4);
builder.installSteering(1);
builder.installAccelerator(1);
builder.installClutch(1);
builder.installGasolineEngine("国产汽油发动机");
builder.installTop("一块铁板");
}
}
最后看下客户端如何调用:
/**
* 获得一辆汽车(具体产品),客户需要主管和具体生成器,无需知道生产汽车的具体过程和细节
*/
public class client {
public static void main(String[] args) {
/**
* 获取主管类(“拿起生成器说明书并操作生成器”)
*/
CarDirector director = new CarDirector();
/**
* 制造保时捷
*/
PoscheBuilder poscheBuilder = new PoscheBuilder();
// 主管类操作保时捷生成器,在生成卡车前先进行一些安装工作
director.producePosche(poscheBuilder);
// 设置完成后,生产我的保时捷
Posche myPosche = (Posche) poscheBuilder.getCar();
// 查看保时捷成品
myPosche.info();
/**
* 制造五菱宏光
*/
WulingBuilder wulingBuilder = new WulingBuilder();
// 主管类操作五菱宏光生成器,在生成卡车前先进行一些安装工作
director.produceWuling(wulingBuilder);
// 设置完成后,生产你的五菱宏光
Wuling yourWuling = (Wuling) wulingBuilder.getCar();
// 查看五菱宏光成品
yourWuling.info();
}
}
生成器模式总结
- 产品(对象)生成具有滞后性。与工厂模式中的工厂不同,生成器模式中的“生成器”并不负责生产最终的产品,最终的产品是在“主管”手中生成的。
- 生成器干了点什么?在本文的故事背景中,生成器在生产汽车前,准备好了所有零件、实现了每一个步骤。
- 主管类干了点什么?主管指挥着生成器,组装出最后的汽车产品。当然主管要有宏观把控的能力,造不同的汽车分别需要哪些步骤,这些步骤是怎样的执行顺序,都是主管类实现的(想想你的大leader,是不是每天指挥程序猿就行了,早就不用自己写代码了?)。
- 抽象产品类:可以有,但没必要。本文的栗子中两个具体产品都继承自同一抽象产品,给人一种错觉:生成器模式也是要生产同一系列。事实上生成器模式的目的不是生产同一系列的产品,只要这些产品的属性或者生成过程相似,就可以用生成器模式。
共同学习,欢迎交流!
这里是源码