zoukankan      html  css  js  c++  java
  • 设计模式——建造者模式

    建造者模式又名生成器模式,可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

    使用场景:类的实例属性过多时,构造方法可能会很多;虽然我们可以用JavaBean的setter方法进行设置,但生成的对象状态可能不一致,导致对象不可用。最常见的:只赋值一部分属性,就拿去使用了,会导致NullPointerException异常。

    这个时候就可以使用建造者模式,这也是《Effective Java》中推荐的。

    • 可以极大的简化代码,不用创建多个构造器。
    • 并且还能保证对象的一致性,在最后调用build()方法时,对象才是可用的。

    建造者模式的常用实现方式:

    一、内部静态类

    public class NutritionFacts {
        private final int servingSize;
        private final int servings;
        private final int calories;
        private final int fat;
        private final int sodium;
        private final int carbohydrate;
    
        private NutritionFacts(Builder builder){
            this.servingSize = builder.servingSize;
            this.servings = builder.servings;
            this.calories = builder.calories;
            this.fat = builder.fat;
            this.sodium = builder.sodium;
            this.carbohydrate = builder.carbohydrate;
        }
    
        public static class Builder{
            private final int servingSize;
            private final int servings;
            private int calories;
            private int fat;
            private int sodium;
            private int carbohydrate;
    
            public Builder(int servingSize, int servings){
                this.servingSize = servingSize;
                this.servings = servings;
            }
    
            public Builder calories(int calories){
                this.calories = calories;
                return this;
            }
    
            public Builder fat(int fat){
                this.fat = fat;
                return this;
            }
    
            public Builder sodium(int sodium){
                this.sodium = sodium;
                return this;
            }
    
            public Builder carbohydrate(int carbohydrate){
                this.carbohydrate = carbohydrate;
                return this;
            }
    
            public NutritionFacts build(){
                return new NutritionFacts(this);
            }
        }
    }

     二、框架中的建造者模式

    1、Mybatis的二级缓存初始化

    之前装饰者模式主要说的是二级缓存的增强,二级缓存的对象初始化其实就是一个建造者模式。

    /* org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache */
      public Cache useNewCache(Class<? extends Cache> typeClass,
          Class<? extends Cache> evictionClass,
          Long flushInterval,
          Integer size,
          boolean readWrite,
          boolean blocking,
          Properties props) {
          //建造器模式创建cache
        Cache cache = new CacheBuilder(currentNamespace)
            .implementation(valueOrDefault(typeClass, PerpetualCache.class))
            .addDecorator(valueOrDefault(evictionClass, LruCache.class))
            .clearInterval(flushInterval)
            .size(size)
            .readWrite(readWrite)
            .blocking(blocking)
            .properties(props)
            .build();
        configuration.addCache(cache);
        currentCache = cache;
        return cache;
      }

    来看看CacheBuilder的具体实现。

    ①、CacheBuilder的八个私有变量

      private final String id;//Cache的id
      private Class<? extends Cache> implementation;//Cache的实例类
      private final List<Class<? extends Cache>> decorators;//Cache的装饰类
      private Integer size;//Cache大小
      private Long clearInterval;//不为空时创建ScheduledCache装饰者实例,定时清理缓存(过期时间)
      private boolean readWrite;//为true时创建SerializedCache装饰者实例,将缓存value写时序列化存储,读时反序列化,因此value需要实现Serializable接口
      private Properties properties;//Cache初始化时缓存的键值对
      private boolean blocking;//为true时创建BlockingCache装饰者实例,阻塞缓存(每个key/value都会创建一个独占锁ReentranLock),读取缓存时阻塞(加锁),有修改或者删除时释放锁。

    ②、CacheBuilder构造方法及参数设置

      /*
       * 构造方法
       */
       public CacheBuilder(String id) {
        this.id = id;
        this.decorators = new ArrayList<Class<? extends Cache>>();
      }
    
      /*
       * 参数设置
       */
      public CacheBuilder implementation(Class<? extends Cache> implementation) {
        this.implementation = implementation;
        return this;
      }
    
      public CacheBuilder addDecorator(Class<? extends Cache> decorator) {
        if (decorator != null) {
          this.decorators.add(decorator);
        }
        return this;
      }
    
      public CacheBuilder size(Integer size) {
        this.size = size;
        return this;
      }
    
      public CacheBuilder clearInterval(Long clearInterval) {
        this.clearInterval = clearInterval;
        return this;
      }
    
      public CacheBuilder readWrite(boolean readWrite) {
        this.readWrite = readWrite;
        return this;
      }
    
      public CacheBuilder blocking(boolean blocking) {
        this.blocking = blocking;
        return this;
      }
    
      public CacheBuilder properties(Properties properties) {
        this.properties = properties;
        return this;
      }

    ③、Cache初始化CacheBuilder.build()

      public Cache build() {
        //Cache实例类implementation,为空则默认:PerpetualCache.class
        //Cache装饰类decorators,为空则默认:LruCache.class
        setDefaultImplementations();
        //反射创建缓存实例: 类似new PerpetualCache(id)
        Cache cache = newBaseCacheInstance(implementation, id);
        //将properties放入到cache中
        setCacheProperties(cache);
        //PerpetualCache缓存实例允许装饰者初始化 decorators+size+clearInterval+readWrite+blocking
        if (PerpetualCache.class.equals(cache.getClass())) {
          for (Class<? extends Cache> decorator : decorators) {
            cache = newCacheDecoratorInstance(decorator, cache);
            setCacheProperties(cache);
          }
          cache = setStandardDecorators(cache);
        } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
          cache = new LoggingCache(cache);
        }
        //最后返回一个可用的Cache实例
        return cache;
      }

    总结:Builder模式,有两个类Builder、Object

    Builder初始化Object的参数,并使用Builder.build()返回一个可用的Object对象

    • Object不用创建多个构造器。
    • 并且还能保证对象的一致性,在最后调用build()方法时,Object对象才是可用的。

     

  • 相关阅读:
    Spring笔记:常用xml标签和属性 山上下了雪
    Spring笔记:Hello World 山上下了雪
    Spring笔记:bean的自动装配 山上下了雪
    IntelliJ IDEA 2020.3.3 x64破解到2099年
    每日长进计划
    idea测试类中的测试方法没有运行按钮
    删除所有的phpfpm进程命令
    高质量编程
    单例模式也能玩出花
    宝塔Linux面板安装命令
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12627062.html
Copyright © 2011-2022 走看看