简介
生成器模式的核心是当构建一个对象的时候,需要包含多个步骤,虽然每个步骤具体的实现不同,但是都遵循一定的流程和规则。比如组装一辆汽车,需要引擎、座位、变速箱、定位器、行车电脑等,但不管怎么样,总需要经过一个一个步骤构建,对于这个例子,通过一个总控管理生成器,就可以使用生成器模式来生成一辆车及其使用说明书,需要通过多个步骤来生成
可以将生成器模式理解为,假设有一个对象需要建立,这个对象由多个组件组合而成,每个组件的建立都比较复杂,但运用组件来建立所需的对象非常简单,所以就可以将构建复杂附件的步骤与运用组件构建对象分离,使用生成器模式建立
实现
- 汽车组件类 --- 构造产品所需要组件
- 引擎
-
import lombok.Data; @Data 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 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; } public boolean isStarted() { return started; } }
-
- GPS追踪器
-
import lombok.Data; @Data 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; } }
-
- 变速箱类型
-
public enum Transmission { /**单冲程*/ SINGLE_SPEED, /**手动挡*/ MANUAL, /**自动挡*/ AUTOMATIC, /**半主动档*/ SEMI_AUTOMATIC; }
-
- 行车电脑
-
import lombok.Data; @Data 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"); } } }
-
- 引擎
- 产品类
- 汽车类型
-
public enum CarType { CITY_CAR, SPORTS_CAR, SUV; }
-
- 汽车
-
import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class Car { /**汽车类型*/ private final CarType carType; /**座位数*/ private final int seats; /**引擎*/ private final Engine engine; /**变速箱*/ private final Transmission transmission; /**行车电脑*/ private final TripComputer tripComputer; /**定位器*/ private final GPSNavigator gpsNavigator; /**燃料*/ private double fuel = 0.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; this.gpsNavigator = gpsNavigator; } }
-
- 汽车手册
-
import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor 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; /** * 获取手册信息 * @return 手册信息 */ 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; } }
-
- 汽车类型
- 构造器 --- 清晰地定义通用步骤, 确保它们可以制造所有形式的产品
- 父类构造器 --- 在基本生成器接口中声明通用步骤
-
public interface Builder { /** * 汽车类型 * @param carType */ void setCarType(CarType carType); /** * 座位数 * @param seats */ void setSeats(int seats); /** * 引擎 * @param engine */ void setEngine(Engine engine); /** * 变速箱 * @param transmission */ void setTransmission(Transmission transmission); /** * 行车电脑 * @param tripComputer */ void setTripComputer(TripComputer tripComputer); /** * 定位器 * @param gpsNavigator */ void setGPSNavigator(GPSNavigator gpsNavigator); }
-
- 汽车构造器 --- 为每个形式的产品创建具体生成器类, 并实现其构造步骤
-
public class CarBuilder implements Builder{ private CarType carType; private int seats; private Engine engine; private GPSNavigator gpsNavigator; private Transmission transmission; private TripComputer tripComputer; @Override public void setCarType(CarType carType) { this.carType = carType; } @Override public void setSeats(int seats) { this.seats = seats; } @Override public void setEngine(Engine engine) { this.engine = engine; } @Override public void setTransmission(Transmission transmission) { this.transmission = transmission; } @Override public void setTripComputer(TripComputer tripComputer) { this.tripComputer = tripComputer; } @Override public void setGPSNavigator(GPSNavigator gpsNavigator) { this.gpsNavigator = gpsNavigator; } /**实现获取构造结果对象的方法。 你不能在生成器接口中声明该方法, 因为不同生成器构造的产品可能没有公共接口, 因此你就不知道该方法返回的对象类型。 但是, 如果所有产品都位于单一类层次中, 你就可以安全地在基本接口中添加获取生成对象的方法*/ public Car getResult(){ return new Car(carType,seats,engine,transmission,tripComputer,gpsNavigator); } }
-
- 汽车手册构造器 --- 为每个形式的产品创建具体生成器类, 并实现其构造步骤
-
public class CarManualBuilder implements Builder{ private CarType type; private int seats; private Engine engine; private Transmission transmission; private TripComputer tripComputer; private GPSNavigator gpsNavigator; @Override public void setCarType(CarType carType) { this.type = carType; } @Override public void setSeats(int seats) { this.seats = seats; } @Override public void setEngine(Engine engine) { this.engine = engine; } @Override public void setTransmission(Transmission transmission) { this.transmission = transmission; } @Override public void setTripComputer(TripComputer tripComputer) { this.tripComputer = tripComputer; } @Override public void setGPSNavigator(GPSNavigator gpsNavigator) { this.gpsNavigator = gpsNavigator; } /**实现获取构造结果对象的方法。 你不能在生成器接口中声明该方法, 因为不同生成器构造的产品可能没有公共接口, 因此你就不知道该方法返回的对象类型。 但是, 如果所有产品都位于单一类层次中, 你就可以安全地在基本接口中添加获取生成对象的方法*/ public Manual getResult(){ return new Manual(type,seats,engine,transmission,tripComputer,gpsNavigator); } }
-
- 父类构造器 --- 在基本生成器接口中声明通用步骤
- 主管控制生成器 --- 考虑创建主管类。 它可以使用同一生成器对象来封装多种构造产品的方式
-
public class Diretor { private Builder builder; public Diretor(){ } public Diretor(Builder builder){ this.builder = 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()); } 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()); } public void constructSUV(Builder builder) { builder.setCarType(CarType.SUV); builder.setSeats(4); builder.setEngine(new Engine(2.5, 0)); builder.setTransmission(Transmission.MANUAL); builder.setTripComputer(new TripComputer()); builder.setGPSNavigator(new GPSNavigator()); } public void setBuilder(Builder builder) { this.builder = builder; } }
-
- 测试 --- 客户端代码会同时创建生成器和主管对象
-
public class Test { public static void main(String[] args) { //构造开始前, 客户端必须将生成器对象传递给主管对象。 通常情况下, 客户端只需调用主管类构造函数一次即可,主管类使用生成器对象完成后续所有制造任务 //还有另一种方式, 那就是客户端可以将生成器对象直接传递给主管类的制造方法 CarBuilder carBuilder = new CarBuilder(); new Diretor().constructCityCar(carBuilder); //只有在所有产品都遵循相同接口的情况下, 构造结果可以直接通过主管类获取。 否则, 客户端应当通过生成器获取构造结果 Car car = carBuilder.getResult(); car.setFuel(20D); System.out.println(car.getCarType()); CarManualBuilder carManualBuilder = new CarManualBuilder(); new Diretor().constructCityCar(carManualBuilder); System.out.println(carManualBuilder.getResult().print()); } }
CITY_CAR Type of car: CITY_CAR Count of seats: 2 Engine: volume - 1.2; mileage - 0.0 Transmission: AUTOMATIC Trip Computer: Functional GPS Navigator: Functional
-
优势和缺点
优势:
- 分步创建对象, 暂缓创建步骤或递归运行创建步骤
- 生成不同形式的产品时, 可以复用相同的制造代码
- 单一职责原则。 可以将复杂构造代码从产品的业务逻辑中分离出来
缺点:
- 由于该模式需要新增多个类, 因此代码整体复杂程度会有所增加
应用场景
-
如果需要创建的各种形式的产品, 它们的制造过程相似且仅有细节上的差异, 此时可使用生成器模式
- 基本生成器接口中定义了所有可能的制造步骤, 具体生成器将实现这些步骤来制造特定形式的产品。 同时, 主管类将负责管理制造步骤的顺序
参考 https://refactoringguru.cn/design-patterns/builder
标签:builder,--,void,生成器,private,seats,设计模式,public From: https://www.cnblogs.com/52-IT-y/p/16659963.html