设计模式——建造者模式

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

使用场景:类的实例属性过多时,构造方法可能会很多;虽然我们可以用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对象才是可用的。

 

posted on 2020-04-03 16:05  FFStayF  阅读(201)  评论(0编辑  收藏  举报