装饰者模式:动态地将责任附加到对象上。 若要扩展功能,装饰者提供了比继承更有弹性的替代方案(head first设计模式)。
应用场景:当原有的类不能满足我们的需求时,我们可能设计一个类去继承它,但这种做法违反了开放-关闭原则(要对扩展开放,对修改关闭。多用组合,少用继承。高内聚低耦合),会导致对象之间高度耦合,所以尽量采用组合方式而不使用继承方式去扩展新功能。
tip:目前增强类功能的手段有三种:
1、继承:特点是在编译时静态决定被增强对象的新功能。
2、装饰者模式:特点是运行时动态地扩展被增强对象的新功能。
3、动态代理:特点是通过反射获取被增强对象,再在执行相应方法时动态地扩展被增强对象的新功能。
装饰者模式的组件:
- Component(被装饰对象的基类,一般是抽象类或者接口)
- ConcreteComponent(具体被装饰对象,继承或实现Component)
- Decorator(装饰者抽象类或者接口,此类是为了扩充装饰类本身,实现多样化装饰而派生出来的顶层抽象装饰类,此类在某些场景下可以不用创建,会维持一个指向Component实例的引用,并拥有和Component一致的超类)
- ConcreteDecorator(具体装饰者)
装饰者模式组件示例:
示例一(用最常见的Java IO体系做例子):
示例二(用Mybatis源码的Executor做例子):
具体代码请参考IO源码与Mybatis源码,此处就不列举了。
装饰者模式总结:
- 装饰者和被装饰对象必须有相同的超类型。
- 你可以用一个或多个装饰者包装一个对象。
- 既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它。
- 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。
- 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
- 实现的方法通常是把原有类作为装饰类构造函数的一个参数进行传入。
- 装饰器必须实现被装饰类的所有方法,并在这些方法中一般还要求调用被装饰类的对应方法,一次实现对被修饰类对象数据的操作(对象的数据一般都只能通过它自己的方法接口进行操作)。
- 为了扩充装饰类本身,实现多样化装饰,一般会先派生一个顶层的抽象装饰类(如java.io.FilterInputStream),再从这个抽象的装饰类派生一些具体的装饰类。