设计模式——建造者模式
建造者模式又名生成器模式,可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。
使用场景:类的实例属性过多时,构造方法可能会很多;虽然我们可以用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对象才是可用的。