什么是装饰者模式设计模式
在不改变原有对象的基础上附加功能,相比生成子类更灵活。缓存
装饰者模式应用场景安全
Mybatis缓存,过滤器,网关控制,P2P分控审批app
装饰者模式定义源码分析
(1)抽象组件:定义一个抽象接口,来规范准备附加功能的类ui
(2)具体组件:将要被附加功能的类,实现抽象构件角色接口this
(3)抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口spa
(4)具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。debug
定义一个接口设计
public interface ComponentCatch { /** * 定义共同行为的方法标准 */ Object getCatch(String key); void putCatch(String key,Object value); }
定义被装饰角色
/** * 【一级缓存】,FirstCatch【被装饰的类】 */ public class FirstCatch implements ComponentCatch { //假装成一级缓存 HashMap firstCatchMap=new HashMap(); public FirstCatch() { firstCatchMap.put("1","xuyu"); } public Object getCatch(String key) { Object value = firstCatchMap.get(key); System.out.println(">>>>>>>调用一级缓存查询数据"); return value; } public void putCatch(String key, Object value) { firstCatchMap.put(key,value); } }
定义抽象装饰角色
/** * 抽象装饰者:AbstractDecorator,定义【被装饰者】与【具体装饰者】共同行为 */ public abstract class AbstractDecorator implements ComponentCatch { protected ComponentCatch baseCatch; public AbstractDecorator(ComponentCatch baseCatch) { this.baseCatch = baseCatch; } public Object getCatch(String key) { return baseCatch.getCatch(key); } }
定义具体装饰角色
/** * 二级缓存:SecondCatch,【装饰者】 * SecondCatch:在不改变原有一级缓存基础之上搭建二级缓存 */ public class SecondCatch extends AbstractDecorator { //假装成二级缓存 HashMap secondCatchMap=new HashMap(); public SecondCatch(ComponentCatch baseCatch) { super(baseCatch); } public Object getCatch(String key) { System.out.println(">>>>>>>调用二级缓存查询数据"); //先查询二级缓存 Object secondValue = secondCatchMap.get(key); //若是二级缓存没有,再查询一级缓存 if(secondValue==null){ Object firstValue = super.getCatch(key); //若是一级缓存有的话 if(firstValue!=null){ //将一级缓存缓存到二级缓存 secondCatchMap.put(key,firstValue); secondValue=firstValue; } } return secondValue; } public void putCatch(String key, Object value) { } }
/** * 三级缓存【装饰者】 * ThiredCatch:在不改变原有二级缓存的基础之上搭建三级缓存 */ public class ThiredCatch extends AbstractDecorator { //假装成三级缓存 HashMap thiredCatchMap=new HashMap(); public ThiredCatch(ComponentCatch baseCatch) { super(baseCatch); } public void putCatch(String key, Object value) { } public Object getCatch(String key) { System.out.println(">>>>>>>调用三级缓存查询数据"); //先查询三级缓存 Object thiredValue = thiredCatchMap.get(key); //若是三级缓存没有,再查询二级缓存,若是二级缓存为空的话,再查询一级缓存 if(thiredValue==null){ Object secondValue = super.getCatch(key); //若是二级缓存不为空 if(secondValue!=null){ //将二级缓存缓存到三级缓存 thiredCatchMap.put(key,secondValue); thiredValue=secondValue; } } return thiredValue; } }
获取装饰类
public class FactoryCatch { public static ComponentCatch getComponentCatch(){ ThiredCatch thiredCatch = new ThiredCatch(new SecondCatch(new FirstCatch())); return thiredCatch; } public static void main(String[] args) { ComponentCatch getComponentCatch=getComponentCatch(); Object value1 = getComponentCatch.getCatch("1"); System.out.println("value1:"+value1); System.out.println("###########################"); Object value2 = getComponentCatch.getCatch("1"); System.out.println("value2:"+value2); } }
输出结果
>>>>>>>调用三级缓存查询数据
>>>>>>>调用二级缓存查询数据
>>>>>>>调用一级缓存查询数据
value1:xuyu
###########################
>>>>>>>调用三级缓存查询数据
value2:xuyu
部分源码
public Cache useNewCache(Class<? extends Cache> typeClass, Class<? extends Cache> evictionClass, Long flushInterval, Integer size, boolean readWrite, boolean blocking, Properties props) { typeClass = valueOrDefault(typeClass, PerpetualCache.class); evictionClass = valueOrDefault(evictionClass, LruCache.class); Cache cache = new CacheBuilder(currentNamespace) .implementation(typeClass) //添加二级缓存 .addDecorator(evictionClass) .clearInterval(flushInterval) .size(size) .readWrite(readWrite) .blocking(blocking) .properties(props) .build(); configuration.addCache(cache); currentCache = cache; return cache; }
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { //获取二级缓存 Cache cache = ms.getCache(); //判断二级缓存是否存在 if (cache != null) { flushCacheIfRequired(ms); if (ms.isUseCache() && resultHandler == null) { ensureNoOutParams(ms, parameterObject, boundSql); @SuppressWarnings("unchecked") List<E> list = (List<E>) tcm.getObject(cache, key); if (list == null) { list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); tcm.putObject(cache, key, list); // issue #578 and #116 } return list; } } return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); }
public Object getObject(Object key) { requests++; //这里获取二级缓存 final Object value = delegate.getObject(key); if (value != null) { hits++; } if (log.isDebugEnabled()) { log.debug("Cache Hit Ratio [" + getId() + "]: " + getHitRatio()); } return value; }
总结:
装饰模式和代理模式区别?
代理模式:在方法以前和以后实现处理,在方法上实现加强,隐藏真实方法的真实性,保证安全。
装饰模式:不改变原有的功能,实现加强,不断新增不少装饰。
知识分享
本文参考:蚂蚁课堂:http://www.mayikt.com