什么是装饰者模式
在不改变原有对象的基础上附加功能,相比生成子类更灵活。
装饰者模式应用场景
Mybatis缓存,过滤器,网关控制,P2P分控审批
装饰者模式定义
(1)抽象组件:定义一个抽象接口,来规范准备附加功能的类
(2)具体组件:将要被附加功能的类,实现抽象构件角色接口
(3)抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口
(4)具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。
定义一个接口
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 List 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 list = (List) tcm.getObject(cache, key);
if (list == null) {
list = delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
return delegate. 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