设计模式--生成器模式

简介

生成器模式的核心是当构建一个对象的时候,需要包含多个步骤,虽然每个步骤具体的实现不同,但是都遵循一定的流程和规则。比如组装一辆汽车,需要引擎、座位、变速箱、定位器、行车电脑等,但不管怎么样,总需要经过一个一个步骤构建,对于这个例子,通过一个总控管理生成器,就可以使用生成器模式来生成一辆车及其使用说明书,需要通过多个步骤来生成

可以将生成器模式理解为,假设有一个对象需要建立,这个对象由多个组件组合而成,每个组件的建立都比较复杂,但运用组件来建立所需的对象非常简单,所以就可以将构建复杂附件的步骤与运用组件构建对象分离,使用生成器模式建立


实现

  • 汽车组件类 --- 构造产品所需要组件
    • 引擎
      • 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

优势和缺点

优势:

  • 分步创建对象 暂缓创建步骤或递归运行创建步骤
  • 生成不同形式的产品时 可以复用相同的制造代码
  • 可以将复杂构造代码从产品的业务逻辑中分离出来

缺点:

  • 由于该模式需要新增多个类 因此代码整体复杂程度会有所增加

应用场景

  • 如果需要创建的各种形式的产品 它们的制造过程相似且仅有细节上的差异 此时可使用生成器模式

     

    • 基本生成器接口中定义了所有可能的制造步骤 具体生成器将实现这些步骤来制造特定形式的产品 同时 主管类将负责管理制造步骤的顺序

Java 中使用案例

生成器在 Java 核心程序库中得到了广泛的应用

  • java.lang.StringBuilder#append()  非同步 
  • java.lang.StringBuffer#append()  同步 

识别方法 生成器模式可以通过类来识别 它拥有一个构建方法和多个配置结果对象的方法 生成器方法通常支持方法链 例如 someBuilder.​setValueA(1).​setValueB(2).​create()


参考 https://refactoringguru.cn/design-patterns/builder

posted @   伊文小哥  阅读(71)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示