一、定义
生成器模式:是一种创建型设计模式,使你能够分布创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。
二、介绍
假设有这样一个复杂对象,在对其进行构造时需要对诸多成员变量和嵌套对象进行繁复的初始化工作。这些初始化代码通常深藏于一个包含众多参数且让人基本看不懂的构造函数中;甚至还有更糟糕的情况,那就是这些代码散落在客户端代码的多个位置。
例如, 我们来思考如何创建一个 房屋
House对象。 建造一栋简单的房屋, 首先你需要建造四面墙和地板, 安装房门和一套窗户, 然后再建造一个屋顶。 但是如果你想要一栋更宽敞更明亮的房屋, 还要有院子和其他设施 (例如暖气、 排水和供电设备), 那又该怎么办呢?
最简单的方法是扩展 房屋
基类, 然后创建一系列涵盖所有参数组合的子类。 但最终你将面对相当数量的子类。 任何新增的参数 (例如门廊类型) 都会让这个层次结构更加复杂
另一种方法则无需生成子类。 你可以在 房屋
基类中创建一个包括所有可能参数的超级构造函数, 并用它来控制房屋对象。 这种方法确实可以避免生成子类, 但它却会造成另外一个问题:
通常情况下, 绝大部分的参数都没有使用, 这使[对于构造函数的调用十分不简洁。 例如, 只有很少的房子有游泳池, 因此与游泳池相关的参数十之八九是毫无用处的。
三、解决方案
生成器模式建议将对象构造代码从产品类中抽取出来, 并将其放在一个名为生成器的独立对象中。
该模式会将对象构造过程划分为一组步骤, 比如 buildWalls
创建墙壁和 buildDoor
创建房门创建房门等。 每次创建对象时, 你都需要通过生成器对象执行一系列步骤。 重点在于你无需调用所有步骤, 而只需调用创建特定对象配置所需的那些步骤即可。
当你需要创建不同形式的产品时, 其中的一些构造步骤可能需要不同的实现。 例如, 木屋的房门可能需要使用木头制造, 而城堡的房门则必须使用石头制造。
在这种情况下, 你可以创建多个不同的生成器, 用不同方式实现一组相同的创建步骤。 然后你就可以在创建过程中使用这些生成器 (例如按顺序调用多个构造步骤) 来生成不同类型的对象。
例如, 假设第一个建造者使用木头和玻璃制造房屋, 第二个建造者使用石头和钢铁, 而第三个建造者使用黄金和钻石。 在调用同一组步骤后, 第一个建造者会给你一栋普通房屋, 第二个会给你一座小城堡, 而第三个则会给你一座宫殿。 但是, 只有在调用构造步骤的客户端代码可以通过通用接口与建造者进行交互时, 这样的调用才能返回需要的房屋
你可以进一步将用于创建产品的一系列生成器步骤调用抽取成为单独的主管类。 主管类可定义创建步骤的执行顺序, 而生成器则提供这些步骤的实现
严格来说, 你的程序中并不一定需要主管类。 客户端代码可直接以特定顺序调用创建步骤。 不过, 主管类中非常适合放入各种例行构造流程, 以便在程序中反复使用。
此外, 对于客户端代码来说, 主管类完全隐藏了产品构造细节。 客户端只需要将一个生成器与主管类关联, 然后使用主管类来构造产品, 就能从生成器处获得构造结果了。
-
角色划分
- 生成器(Builder):声明在所有类型生成器中通用的产品构造步骤
- 具体生成器(Concrete Builder):提供构造过程的不同实现。具体生成器也可以构造不遵循通用接口的产品
- 产品(Products):最终生成的对象。由不同生成器构造的产品无需属于同一类层次结构或接口
- 主管类(Director):定义调用构造步骤的顺序,这样你就可以创建和复用特定的产品配置
- 客户端(Client):必须将某个生成器对象与主管类关联。一般情况下,你只需要通过主管类构造函数的参数进行一次性关联即可。此后主管类就能使用生成器对象完成后续所有的构造任务。但在客户端将生成器对象传递给主管类制造方法时还有另一种方式。在这种情况下,在使用主管类生产产品时每次都可以使用不同的生成器
四、实现
案例一:使用生成器模式实现:分步制造不同型号的汽车和对应的汽车手册
案例解析:
1.角色拆分:
- 通用生成器:设置汽车类型、座位数、引擎、汽车特征等
- 具体生成器:汽车生成器、汽车手册生成器
- 产品:汽车、手册、
- 主管类:创建运动型汽车、创建城市型汽车、创建SUV型汽车等
-
创建汽车相关类:汽车类型类、引擎类、汽车特征类
- 汽车类型枚举类 CarType
public enum CarType { /** * 城市型 */ CITY_CAR, /** * 运动型 */ SPORTS_CAR, /** * SUV */ SUV }
- 汽车引擎类 Engine
public class Engine { /** * 体积 */ private final double volume; /** * 里程 */ private double mileage; /** * 汽车引擎启动标识 */ private boolean started; public Engine(double volume, double mileage) { this.volume = volume; this.mileage = mileage; } /** * 启动引擎 */ public void on() { started = true; } /** * 关闭引擎 */ public void off() { started = false; } public boolean isStarted() { return started; } /** * 行驶里程 * @param mileage 里程数 */ public void go(double mileage) { if (started) { this.mileage += mileage; } else { System.err.println("Cannot go(), you must start engine first!"); } } public double getVolume() { return volume; } public double getMileage() { return mileage; } }
- 汽车GPS特征类 GPSNavigator
public class GPSNavigator { /** * 导航路径 */ private String route; public GPSNavigator() { this.route = "221b, Baker Street, London to Scotland Yard, 8-10 Broadway, London"; } public GPSNavigator(String manualRoute) { this.route = manualRoute; } public String getRoute() { return route; } }
- 汽车其他特征类 Transmission、TripComputer
public enum Transmission { SINGLE_SPEED, // 单速 MANUAL, // 手动 AUTOMATIC, // 自动 SEMI_AUTOMATIC // 半自动 }
public class TripComputer { private Car car; public void setCar(Car car) { this.car = car; } public void showFuelLevel() { System.out.println("Fuel level: " + car.getFuel()); } public void showStatus() { if (this.car.getEngine().isStarted()) { System.out.println("Car is started"); } else { System.out.println("Car isn't started"); } } }
-
创建产品类:汽车产品、汽车手册产品
- 汽车产品类:Car
public class Car { /** * 汽车类型 */ private final CarType carType; /** * 座位数 */ private final int seats; /** * 汽车引擎 */ private final Engine engine; /** * 汽车特征一:动力传输方式 */ private final Transmission transmission; /** * 汽车特征二:行程计算机 */ private final TripComputer tripComputer; /** * 汽车特征三:GPS导航 */ private final GPSNavigator gpsNavigator; /** * 汽车燃料 */ private double fuel = 0; /** * 创建汽车产品 */ public Car(CarType carType, int seats, Engine engine, Transmission transmission, TripComputer tripComputer, GPSNavigator gpsNavigator) { this.carType = carType; this.seats = seats; this.engine = engine; this.transmission = transmission; this.tripComputer = tripComputer; if (this.tripComputer != null) { this.tripComputer.setCar(this); } this.gpsNavigator = gpsNavigator; } public CarType getCarType() { return carType; } public double getFuel() { return fuel; } public void setFuel(double fuel) { this.fuel = fuel; } public int getSeats() { return seats; } public Engine getEngine() { return engine; } public Transmission getTransmission() { return transmission; } public TripComputer getTripComputer() { return tripComputer; } public GPSNavigator getGpsNavigator() { return gpsNavigator; } }
- 汽车手册产品类:Manual
public class Manual { private final CarType carType; private final int seats; private final Engine engine; private final Transmission transmission; private final TripComputer tripComputer; private final GPSNavigator gpsNavigator; public Manual(CarType carType, int seats, Engine engine, Transmission transmission, TripComputer tripComputer, GPSNavigator gpsNavigator) { this.carType = carType; this.seats = seats; this.engine = engine; this.transmission = transmission; this.tripComputer = tripComputer; this.gpsNavigator = gpsNavigator; } public String print() { String info = ""; info += "Type of car: " + carType + "\n"; info += "Count of seats: " + seats + "\n"; info += "Engine: volume - " + engine.getVolume() + "; mileage - " + engine.getMileage() + "\n"; info += "Transmission: " + transmission + "\n"; if (this.tripComputer != null) { info += "Trip Computer: Functional" + "\n"; } else { info += "Trip Computer: N/A" + "\n"; } if (this.gpsNavigator != null) { info += "GPS Navigator: Functional" + "\n"; } else { info += "GPS Navigator: N/A" + "\n"; } return info; } }
-
创建通用生成器接口:Builder
public interface Builder {
/**
* 设置汽车类型
*/
void setCarType(CarType type);
/**
* 设置汽车座位数
*/
void setSeats(int seats);
/**
* 设置汽车引擎
*/
void setEngine(Engine engine);
/**
* 设置汽车动力传输方式
*/
void setTransmission(Transmission transmission);
/**
* 设置汽车行程计算机
*/
void setTripComputer(TripComputer tripComputer);
/**
* 设置汽车GPS
*/
void setGPSNavigator(GPSNavigator gpsNavigator);
}
-
创建具体生成器类:汽车生成器和手册生成器
- 汽车生成器:CarBuilder
public class CarBuilder implements Builder { private CarType type; private int seats; private Engine engine; private Transmission transmission; private TripComputer tripComputer; private GPSNavigator gpsNavigator; /** * 设置汽车类型 * * @param type */ @Override public void setCarType(CarType type) { this.type = type; } /** * 设置汽车座位数 * * @param seats */ @Override public void setSeats(int seats) { this.seats = seats; } /** * 设置汽车引擎 * * @param engine */ @Override public void setEngine(Engine engine) { this.engine = engine; } /** * 设置汽车动力传输方式 * * @param transmission */ @Override public void setTransmission(Transmission transmission) { this.transmission = transmission; } /** * 设置汽车行程计算机 * * @param tripComputer */ @Override public void setTripComputer(TripComputer tripComputer) { this.tripComputer = tripComputer; } /** * 设置汽车GPS * * @param gpsNavigator */ @Override public void setGPSNavigator(GPSNavigator gpsNavigator) { this.gpsNavigator = gpsNavigator; } public Car getResult() { return new Car(type, seats, engine, transmission, tripComputer, gpsNavigator); } }
- 手册生成器:CarManualBuilder
public class CarManualBuilder implements Builder { private CarType type; private int seats; private Engine engine; private Transmission transmission; private TripComputer tripComputer; private GPSNavigator gpsNavigator; /** * 设置汽车类型 * * @param type */ @Override public void setCarType(CarType type) { this.type = type; } /** * 设置汽车座位数 * * @param seats */ @Override public void setSeats(int seats) { this.seats = seats; } /** * 设置汽车引擎 * * @param engine */ @Override public void setEngine(Engine engine) { this.engine = engine; } /** * 设置汽车动力传输方式 * * @param transmission */ @Override public void setTransmission(Transmission transmission) { this.transmission = transmission; } /** * 设置汽车行程计算机 * * @param tripComputer */ @Override public void setTripComputer(TripComputer tripComputer) { this.tripComputer = tripComputer; } /** * 设置汽车GPS * * @param gpsNavigator */ @Override public void setGPSNavigator(GPSNavigator gpsNavigator) { this.gpsNavigator = gpsNavigator; } public Manual getResult() { return new Manual(type, seats, engine, transmission, tripComputer, gpsNavigator); } }
-
创建主管类:Director
public class Director {
/**
* 创建运动型号的汽车
* @param builder 关联的生成器
*/
public void constructSportsCar(Builder builder) {
builder.setCarType(CarType.SPORTS_CAR);
builder.setSeats(2);
builder.setEngine(new Engine(3.0, 0));
builder.setTransmission(Transmission.SEMI_AUTOMATIC);
builder.setTripComputer(new TripComputer());
builder.setGPSNavigator(new GPSNavigator());
}
/**
* 创建城市型号的汽车
* @param builder 关联的生成器
*/
public void constructCityCar(Builder builder) {
builder.setCarType(CarType.CITY_CAR);
builder.setSeats(2);
builder.setEngine(new Engine(1.2, 0));
builder.setTransmission(Transmission.AUTOMATIC);
builder.setTripComputer(new TripComputer());
builder.setGPSNavigator(new GPSNavigator());
}
/**
* 创建SUV型号的汽车
* @param builder 关联的生成器
*/
public void constructSUV(Builder builder) {
builder.setCarType(CarType.SUV);
builder.setSeats(4);
builder.setEngine(new Engine(2.5, 0));
builder.setTransmission(Transmission.MANUAL);
builder.setGPSNavigator(new GPSNavigator());
}
}
- 编写客户端类测试:创建运动型汽车和对应的汽车手册
public class ClientTest {
public static void main(String[] args) {
// 创建主管类
Director director = new Director();
// TP 构建汽车产品
// 创建汽车生成器
CarBuilder carBuilder = new CarBuilder();
// 主管类关联具体生成器,如:创建运动型汽车
director.constructSportsCar(carBuilder);
// 获取生成结果
Car car = carBuilder.getResult();
System.out.println("生产汽车的型号:\n" + car.getCarType());
// TP 构建汽车手册产品
// 创建汽车手册生成器
CarManualBuilder carManualBuilder = new CarManualBuilder();
// 主管类关联具体生成器,如:创建运动型汽车手册
director.constructSportsCar(carManualBuilder);
// 获取生成结果
Manual manual = carManualBuilder.getResult();
System.out.println("生产汽车手册信息:\n" + manual.print());
}
}