加载中...

设计模式--创建者模式

设计模式--创建者模式

创建者模式

  • 单例模式:

    /**
     * @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();
        }
    
    }
    
posted @ 2024-02-04 12:28  strind  阅读(17)  评论(0)    收藏  举报