设计模式--装饰器模式
简介
装饰器模式(Decorator Pattern)也成为包装模式(Wrapper Pattern),是指在不改变原有对象的基础上,将功能附加到对象上,提供了比对象更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。
装饰器模式的核心是功能扩展。使用装饰器模式可以透明且动态的扩展类的功能。
装饰器模式主要用于透明且动态的扩展类的功能。其原理为:让装饰器实现被包装类(Concrete Component)相同的接口(Component)(使得装饰器与被扩展类类型一致),并在构造函数中传入该接口(Component)对象,然后就可以在接口需要实现的方法中在被包装类对象的现有功能上添加新功能了。而且由于装饰器与被包装类属于同一类型(均为Component),且构造函数的参数为其实现接口类(Component),因此装饰器模式具备嵌套扩展功能,这样我们就可以使用装饰器一层一层的对最底层被包装类进行功能扩展了。
UML结构图:
抽象组件(Component):可以是一个接口或者抽象类,其充当被装饰类的原始对象,规定了被装饰对象的行为;
具体组件(ConcreteComponent):实现/继承Component的一个具体对象,也即被装饰对象;
抽象装饰器(Decorator):通用的装饰ConcreteComponent的装饰器,其内部必然有一个属性指向Component
抽象组件;其实现一般是一个抽象类,主要是为了让其子类按照其构造形式传入一个Component抽象组件,这是强制的通用行为(当然,如果系统中装饰逻辑单一,并不需要实现许多装饰器,那么我们可以直接省略该类,而直
接实现一个具体装饰器就可以了);
具体装饰器(ConcreteDecorator):Decorator的具体实现类,理论上。每个ConcreteDecorator都扩展了Component对象的一种功能;
装饰器的的应用场景
装饰器在代码中:
1、用于扩展一个类的功能给一个类添加附加职责。
2、动态的给一个对象添加功能,这些功能可以再动态的撤销。
3、需要为兄弟类进行改装或加装功能。
总结:装饰器模式角色分配符合设计模式里氏替换原则,依赖倒置原则,从而使得具备很强的扩展性,最终满足开闭原则。
装饰器在源码中的应用:
- JDK内的IO相关的类(BufferedReader、InputStream、OutputStream)
InputStream
的类结构图
- 在Spring中的TransactionAwareCacheDecorator类,主要用来处理事务缓存
public class TransactionAwareCacheDecorator implements Cache {
private final Cache targetCache;
public TransactionAwareCacheDecorator(Cache targetCache) {
Assert.notNull(targetCache, "Target Cache must not be null");
this.targetCache = targetCache;
}
...
}
TransactionAwareCacheDecorator 就是对 Cache 的一个包装.再来看一个 MVC 中的装饰者模式 HttpHeadResponseDecorator 类
public class HttpHeadResponseDecorator extends ServerHttpResponseDecorator {
public HttpHeadResponseDecorator(ServerHttpResponse delegate) {
super(delegate);
}
...
}
- 在Mybatis中的缓存处理
名字上来看其实更容易理解了.比如 FifoCache 先入先出算法的缓存;LruCache 最近最少使用的缓存;TransactionlCache 事务相关的缓存,都是采用装饰者模式.。
装饰器模式的优缺点:
优点:
1、装饰器是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用
2、通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果
3、装饰者完全遵守开闭原则
缺点:
1、会出现更多的代码,更多的类,增加程序复杂性
2、动态装饰时,多层装饰时会更复杂