首页 > 其他分享 >设计模式--生成器模式

设计模式--生成器模式

时间:2022-09-05 23:26:14浏览次数:65  
标签:builder -- void 生成器 private seats 设计模式 public

简介

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

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


实现

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

相关文章

  • 随手写写(二)
    亲情篇(一)生死 我对于生死的概念一向是理不清道不明的,自从我成为一名医学生后更是不能理解生死,反而能够理解疼痛和苦难。陶勇老师的《自造》第一章讲的是一个走廊,这个走......
  • pandas_pandas_网站log分析
    #读取整个文件夹的log,合并到一个dataframe\1.遍历文件夹读取log\2.然后通过concat函数将这些log合并一个大的dataframe-----------------------------------------......
  • Javaweb-smbms项目搭建
    smbms创建maven项目选择webapp创建配置文件,将web.xml改为4.0版本<?xmlversion="1.0"encoding="UTF-8"?><web-appxmlns="http://xmlns.jcp.org/xml/ns/javaee"......
  • vue3+ts 为原型上添加属性声明
    背景比如在vue2的情况下我们有的时候需要为Vue的原型对象上添加属性或方法,vue3的情况下需要为app挂载全局属性配置,但是结合了ts后,在vue文件中会报警告,但是程序可以正常被......
  • Redis脑裂问题 和 处理办法
    背景假设现在有三台机器,分别安装了redis服务,结构如图故障发生:如果此时master服务器所在区域网络通信出现异常,导致和两台slave机器无法正常通信,但是和客户端的连接是正常......
  • c语音键盘输入和屏幕输出
    键盘输入和屏幕输出单个字符的输入输出getchar字符输入putchar字符输出缓冲区优先每次只读一个字符输出输入量不加引号,只有转义字符加实践:大小写转换注意:getchar()......
  • 使用Visual Studio2022写汇编 代码自动高亮
     本贴帮助使用VS2022写汇编的小伙伴实现代码自动高亮 今天汇编课程老师要求在本地PC上配置一个可以写汇编的环境,选择使用VS2022以及下载的MASM搭建环境。按照网上教程......
  • 设计模式
    1.单例模式:只能创建一个实例的对象。2.单例模式分类两种:饿汉式:类加载就会导致该对象被创建。静态变量的方式:静态代码块方式懒汉式:类加载不会导致该单例对象被创建,而......
  • docker实战教程(四):帮助启动类命令
    启动dockersystemctlstartdocker停止dockersystemctlstopdocker重启dockersystemctlrestartdocker查看docker状态systemctlstatusdocker开机启动syst......
  • Vue-双向数据绑定
    双向数据绑定的源代码<body> <divid="app"> <p>{{data1}}</p> <inputname=""id="":value="data1"@input="fn"> </div> </body> <script> newVue({ ......