首页 > 其他分享 >设计模式--创建者模式

设计模式--创建者模式

时间:2024-02-04 12:33:22浏览次数:22  
标签:return String 创建者 -- public static new 设计模式 class

设计模式--创建者模式

目录

创建者模式

  • 单例模式:

    /**
     * @author strind
     * @version 1.0
     * @description 饿汉式 + 静态成员变量
     * @date 2024/2/3 11:31
     */
    public class ex1 {
    
        private static ex1 instance = new ex1();
    
        // 私有构造方法
        private ex1() { }
    
        // 供外界获取实列
        public static ex1 getInstance(){
            return instance;
        }
    
    }
    
    /**
     * @author strind
     * @version 1.0
     * @description 饿汉式 + 静态代码块
     * @date 2024/2/3 11:31
     */
    public class ex2 {
    
        private static ex2 instance;
    
        static {
            instance = new ex2();
        }
    
        // 私有构造方法
        private ex2() { }
    
        // 供外界获取实列
        public static ex2 getInstance(){
            return instance;
        }
    
    }
    
    /**
     * @author strind
     * @version 1.0
     * @description 懒汉式
     * @date 2024/2/3 11:31
     */
    public class ex3 {
    
        private static ex3 instance;
    
        // 私有构造方法
        private ex3() {
        }
    
        // 供外界获取实列(线程不安全,方法上可以加 synchronized 关键字)
        public static ex3 getInstance(){
            if (Objects.isNull(instance)){
                instance = new ex3();
            }
            return instance;
        }
    
    }
    
    /**
     * @author strind
     * @version 1.0
     * @description 懒汉式 + double-check
     * @date 2024/2/3 11:31
     */
    public class ex4 {
    
        private static ex4 instance;
        //private volatile static ex4 instance;
    
        // 私有构造方法
        private ex4() {}
    
        // 供外界获取实列(线程安全)
        public static ex4 getInstance(){
            // 第一次检查
            if (Objects.isNull(instance)){
                // 多线程时,初次访问时,可能有多个线程走到这里,但只有一个会进去,
                // 此后,其余线程在第一次检查时便会失败,走不到这里
                synchronized (ex4.class){
                    // 第二次检查,同一时间只有一个线程在这里,对象只会被创建一次
                    // 之后的线程无法进入if代码块里
                    if (Objects.isNull(instance)){
                        instance = new ex4();
                    }
                }
            }
            return instance;
        }
        
        /*
        	注意:
        	上面的代码依旧存在问题,在多线程情况下,有可能出现空指针问题,
        	原因是:JVM的指令重排序
        	解决方法:在instance变量上加volatile关键字,避免JVM指令重排
        */
    
    }
    
    /**
     * @author strind
     * @version 1.0
     * @description 懒汉式 + 静态内部类
     * @date 2024/2/3 11:31
     */
    public class ex5 {
    
        // 私有构造方法
        private ex5() {
        }
    
        private static class ex5Holder{
            private static final ex5 INSTANCE = new ex5();
        }
    
        public static ex5 getInstance(){
            return ex5Holder.INSTANCE;
        }
        
        /*
        	由于JVM在加载外部类的过程中,是不会加载静态内部类的,只有内部类的属性/方法被调用时才会加载,并初始化器静态属性。静态属性被static修饰,只会被实例化一次。
        */
        
    }
    
    /**
     * @author strind
     * @version 1.0
     * @description 枚举(饿汉式)
     * @date 2024/2/3 11:31
     */
    public enum ex7 {
        INSTANCE;
    }
    

    破坏单例模式的方法(对枚举方式创建的无效):

    1. 序列化和反序列化
    2. 反射

    解决方法:

    1. 对于序列化和反序列化(添加 readResolve( )方法)

      public class ex5 {
          // 私有构造方法
          private ex5() {
          }
      
          private static class ex5Holder{
              private static final ex5 INSTANCE = new ex5();
          }
      
          public static ex5 getInstance(){
              return ex5Holder.INSTANCE;
          }
          
          // 当进行反序列化时,会自动调用该方法,将该方法的返回值直接返回
          public Object readResolve(){
              return ex5Holder.INSTANCE;
          }
      
      }
      
    2. 对于反射

      public class ex5 {
      
          private static boolean flag = false;
          
          // 私有构造方法
          private ex5() {
              // 在这里解决
              synchronized (ex5.class){
                  if (flag){
                      throw new RuntimeException("你犯规了");
                  }
                  flag = true;
              }
          }
      
          private static class ex5Holder{
              private static final ex5 INSTANCE = new ex5();
          }
      
          public static ex5 getInstance(){
              return ex5Holder.INSTANCE;
          }
      
      }
      
  • 工厂模式:

    1. ​ 简单/静态 工厂,(不属于设计模式,且违背了“开闭原则”)

    2. 工厂方法模式

      /**
       * @author strind
       * @version 1.0
       * @description 工厂方法模式
       * @date 2024/2/4 10:17
       */
      public class factory_method {
      
          public static void main(String[] args) {
              // 生产美式咖啡
              CoffeeStore coffeeStore = new CoffeeStore();
              coffeeStore.setFactory(new AmercianCoffeeFactory());
              String coffee = coffeeStore.orderCoffee().getCoffee();
              System.out.println(coffee);
          }
      
      }
      
      abstract class Coffee{
      
          abstract String getCoffee();
      }
      
      class AmercianCoffee extends Coffee{
      
          @Override
          String getCoffee() {
              return "美式咖啡";
          }
      }
      
      class LatteCoffee extends Coffee{
      
          @Override
          String getCoffee() {
              return "拿铁咖啡";
          }
      }
      
      class CoffeeStore{
      
          private CoffeeFactory factory;
      
          public void setFactory(CoffeeFactory factory){
              this.factory = factory;
          }
          public Coffee orderCoffee(){
              return factory.createCoffee();
          }
      }
      
      interface CoffeeFactory{
          Coffee createCoffee();
      }
      
      class AmercianCoffeeFactory implements CoffeeFactory{
      
          @Override
          public Coffee createCoffee() {
              return new AmercianCoffee();
          }
      }
      
      class LatteCoffeeFactory implements CoffeeFactory{
      
          @Override
          public Coffee createCoffee() {
              return new LatteCoffee();
          }
      }
      
      /*
      	为什么没有违背“开闭原则”:
      		当我们需要添加新的咖啡时,只需要在继承Coffee编写新的咖啡类,和实现CoffeeFactory接口,写新的工厂即可。CoffeeStore类,没有任何更改。对拓展开发,对修改关闭
      */
      

      缺点:拓展时,添加的类较多,增加系统的复杂度,

      原因:工厂类功能唯一

    3. 抽象工厂模式

      /**
       * @author strind
       * @version 1.0
       * @description 抽象工厂
       * @date 2024/2/4 10:41
       */
      public class Abstract_factory {
      
          public static void main(String[] args) {
              // 美式风味
              //AmercianFoodFactory factory = new AmercianFoodFactory();
              // 拿铁风味
              LatteFoodFactory factory = new LatteFoodFactory();
      
              Coffee coffee = factory.createCoffee();
              Dessert dessert = factory.createDessert();
              System.out.println(coffee.getCoffee() + "  " + dessert.getDessert());
          }
      
      }
      
      
      abstract class Coffee{
      
          abstract String getCoffee();
      }
      
      abstract class Dessert{
          abstract String getDessert();
      }
      
      class AmercianCoffee extends Coffee{
      
          @Override
          String getCoffee() {
              return "美式咖啡";
          }
      }
      
      class LatteCoffee extends Coffee{
      
          @Override
          String getCoffee() {
              return "拿铁咖啡";
          }
      }
      
      class Trimisu extends Dessert{
      
          @Override
          String getDessert() {
              return "提拉米苏";
          }
      }
      
      class MatchMousse extends Dessert{
      
          @Override
          String getDessert() {
              return "抹茶慕斯";
          }
      }
      
      
      interface FoodFactory{
          Coffee createCoffee();
      
          Dessert createDessert();
      }
      
      class AmercianFoodFactory implements FoodFactory{
      
          @Override
          public Coffee createCoffee() {
              return new AmercianCoffee();
          }
      
          @Override
          public Dessert createDessert() {
              return new Trimisu();
          }
      }
      
      class LatteFoodFactory implements FoodFactory{
      
          @Override
          public Coffee createCoffee() {
              return new LatteCoffee();
          }
      
          @Override
          public Dessert createDessert() {
              return new MatchMousse();
          }
      }
      
      /*
      	现在一个具体工厂生产的是同一族的产品(例如苹果公司,既有电脑,也有手机,还有paid等。上一个例子则是,只能生产手机或电脑)
      */
      

      缺点:当同一族产品变更时(新增/减少),修改代价较大(工厂都要改变)

    4. 拓展:简单工厂+配置文件

      /**
       * @author strind
       * @version 1.0
       * @description 静态工厂 + 配置文件
       * @date 2024/2/4 11:08
       */
      public class Config_factory {
      
          public static void main(String[] args) {
              Coffee coffee = CoffeeFactory.createCoffee("latte");
              System.out.println(coffee.getCoffee());
          }
      
      }
      
      abstract class Coffee{
      
          abstract String getCoffee();
      }
      
      class AmercianCoffee extends Coffee{
      
      
          @Override
          String getCoffee() {
              return "美式咖啡";
          }
      }
      
      class LatteCoffee extends Coffee{
      
          @Override
          String getCoffee() {
              return "拿铁咖啡";
          }
      }
      
      class CoffeeFactory{
          // 加载配置文件
          private static Map<String,Coffee> map = new HashMap<>();
      
          static {
              Properties properties = new Properties();
              InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");
              try {
                  properties.load(is);
                  Set<Object> keys = properties.keySet();
                  for (Object key : keys) {
                      String className = properties.getProperty((String) key);
                      // 反射创建对象
                      Class<?> clazz = Class.forName(className);
                      Coffee coffee = (Coffee) clazz.newInstance();
                      map.put((String) key,coffee);
                  }
              } catch (Exception e) {
                  throw new RuntimeException(e);
              }
      
          }
      
          public static Coffee createCoffee(String type){
              return map.get(type);
          }
      }
      
      配置文件:
          american=pattern.factory.AmercianCoffee
      	latte=pattern.factory.LatteCoffee
      /**
      	添加新的咖啡,只需要在配置文件中添加即可,没有修改代码,符合“开闭原则”
      
      */    
      
  • 原型模式:理解成克隆就行(注意是浅克隆还是深克隆

    使用场景

    1. 对象的创建非常复杂。
    2. 性能和安全要求比较高
  • 建造者模式:用于较为复杂的对象的构建

    角色:

    • 抽象建造者(Builder):这个接口规定要实行复杂对象的哪些部分的创建,并不涉及具体的部件的创建
    • 具体建造者类(ConcreteBuilder):实现Builder接口,完成复杂产品的各个部件的具体创建方法。在创建过程完成后,提供产品实例
    • 产品类(Product):要创建的复杂对象
    • 指挥者类(Director):调用具体的创建者来创建复杂对象的各个部分,在指挥者种不涉及具体产品的信息,只负责保证对象的各部分完整创建或按某种顺序创建。
    /**
     * @author strind
     * @version 1.0
     * @description 建造者模式 构建自行车
     * @date 2024/2/4 12:00
     */
    public class Bike_build {
    
        public static void main(String[] args) {
            Director director = new Director(new MoBikeBuilder());
    
            Bike bike = director.construct();
            System.out.println(bike.getFrame() + "  " + bike.getSeat());
        }
    
    }
    
    
    class Bike{
        private String frame; // 车架
    
        private String seat; // 车座
    
        public String getFrame() {
            return frame;
        }
    
        public void setFrame(String frame) {
            this.frame = frame;
        }
    
        public String getSeat() {
            return seat;
        }
    
        public void setSeat(String seat) {
            this.seat = seat;
        }
    }
    // 建造者
    abstract class Builder{
        protected Bike bike = new Bike();
    
        public abstract void buildFrame();
        public abstract void buildSeat();
    
        public abstract Bike createBike();
    
    }
    
    class MoBikeBuilder extends Builder{
    
        @Override
        public void buildFrame() {
            bike.setFrame("碳纤维");
        }
    
        @Override
        public void buildSeat() {
            bike.setSeat("真皮");
    
        }
    
        @Override
        public Bike createBike() {
            return bike;
        }
    }
    
    class ofoBuilder extends Builder{
    
        @Override
        public void buildFrame() {
            bike.setFrame("铝合金");
        }
    
        @Override
        public void buildSeat() {
            bike.setSeat("橡胶");
        }
    
        @Override
        public Bike createBike() {
            return bike;
        }
    }
    
    // 指挥者
    class Director{
    
        private Builder builder;
    
        public Director(Builder builder) {
            this.builder = builder;
        }
    
        public Bike construct(){
            builder.buildFrame();
            builder.buildSeat();
            return builder.createBike();
        }
    
    }
    
    // 简化
    将指挥者融入到建造者里
    abstract class Builder{
        protected Bike bike = new Bike();
    
        public abstract void buildFrame();
        public abstract void buildSeat();
    
        public abstract Bike createBike();
        
        public Bike construct(){
            builder.buildFrame();
            builder.buildSeat();
            return builder.createBike();
        }
    
    }
    

标签:return,String,创建者,--,public,static,new,设计模式,class
From: https://www.cnblogs.com/strind/p/18005964

相关文章

  • 鸿蒙:揭晓 ArkTS,重塑语法,打造更健壮和可靠的代码
    hi大家好,我是DHL。就职于美团、快手、小米。公众号:ByteCode,分享有用的原创文章,涉及鸿蒙、Android、Java、Kotlin、性能优化、大厂面经我最近建了一个鸿蒙开发者交流群,群里有大佬说在gitee鸿蒙仓库中可以下载DevEcoStudio4.0。于是我下载体验了一下,运行了官方提供示例项目Sh......
  • 软件测试|人工智能:测试开发的新宠儿
    测试管理班是专门面向测试与质量管理人员的一门课程,通过提升从业人员的团队管理、项目管理、绩效管理、沟通管理等方面的能力,使测试管理人员可以更好的带领团队、项目以及公司获得更快的成长。提供1v1私教指导,BAT级别的测试管理大咖量身打造职业规划。测试是发现问题的艺术,而人......
  • 自己搭一个 OSS 服务,和阿里云的一毛一样
    文件上传是常见需求,一般我们不会直接把文件保存在服务器的某个目录下,因为服务器的存储容量是有限的,这样不好扩展。我们会用OSS(ObjectStorageService)对象存储服务来存文件,它是支持分布式扩展的,不用担心存储容量问题,而且也好管理。比如阿里云的OSS服务。但是有一些业务场景下,数......
  • 面试官:SpringCloudGateway过滤器类型有哪些?
    在SpringCloudGateway中,过滤器是在请求到达目标服务之前或之后,执行某些特定操作的一种机制。例如,它可以实现对传入的请求进行验证、修改、日志记录、身份验证、流量控制等各种功能。在SpringCloudGateway中,过滤器总共分为以下两大类:局部过滤器:只作用于某一个路由(route)。全......
  • 无涯教程-getMonth()函数
    JavaScriptdategetMonth()方法根据本地时间返回指定日期中的月份。getMonth返回的值是0到11之间的整数。0对应于1月,1对应于2月,依此类推。getMonth()-语法Date.getMonth()getMonth()-返回值根据当地时间返回指定日期中的月份。getMonth()-示例vardt=newDate(......
  • SSL证书的验证过程
    HTTPS是工作于SSL层之上的HTTP协议,SSL(安全套接层)工作于TCP层之上,向应用层提供了两个基本安全服务:认证和保密。SSL有三个子协议:握手协议,记录协议和警报协议。其中握手协议实现服务器与客户端的认证与密钥交换,记录协议进行数据加密并保证数据的完整性,警报协议则规定了错误类型和处理......
  • 【Spring】- 生命周期回调
    【Bean初始化】官方使用建议:建议您不要使用InitializingBean接口,因为它不必要地将代码耦合到Spring。另外,我们建议使用@PostConstruct注解或指定POJO初始化方法。对于基于XML的配置元数据,可以使用init-method属性指定具有无效无参数签名的方法的名称spring:1.org.springf......
  • Stable Code 3B:轻量级编程助手,无GPU本地运行
    引言StabilityAI近期发布了StableCode3B,这是一个集中了多项创新技术的轻量级编程辅助模型。它在保持轻量的同时,展现出了与大型模型如CodeLLaMA7B相媲美的性能,这一特性使其在没有GPU的环境中也能运行,极大地拓宽了其应用范围。模型概述StableCode3B,作为一款拥有30亿参数的编程......
  • 一键部署Palworld幻兽帕鲁服务器最佳实践
    本文基于天翼云通用型云主机,为您介绍通过镜像一键部署Palworld幻兽帕鲁服务器的具体操作。Ubuntu系统1.按需购买云主机。通过Palworld专属活动优惠页一键购买开通云主机。 根据需要选择资源池及订购时长,点击立即订购。 支付成功后返回云主机控制台,选择订购云主机所在的资......
  • Windows bat批处理 netsh 设置网络IP
    前言全局说明Windowsbat批处理netsh设置网络IP一、netsh设置网络IP二、Win7系统1.设置IPnetshinterfaceipsetaddressname="本地连接"source=staticaddr=192.168.1.%IP%mask=255.255.255.02>nul1>nul三、Win8、10、11系统1.设置IPnetshinterfaceip......