背景
在项目中运用该设计模式解决了问题,现对其进行总结,为以后思考问题和解决方案做备忘。
是什么
是「面向对象编程」领域中的一种「动态」地往一个「类」中添加新的「行为」的设计模式
在 CPU 看来就是在一段「机器指令」「之前」和「之后」插入新的指令,从而达到动态改变原有指令的「输入参数」和「输出结果」的目的
-
在数据结构上看,类似在一个「链表节点」之前「插入」一个新的节点,这样消息从前向后传递的时候先到达装饰节点再到达被装饰节点
用一个自己的对象「替换」原有对象,「拦截」/「代理」原有对象的所有「消息」,增加/删除原有对象的功能
解决了什么问题
- 通过运用装饰模式,可以在运行时动态增加一个类的功能
- 类继承是「编译时」增加类的行为,装饰模式是「运行时」增加行为(编译出来的程序一般在外存,运行时一般在内存)
- 当有几个「相互独立」的功能需要扩充时,类继承和装饰模式的区别就变得比较明显了。比如对用户头像进行美颜、大眼睛、瓜子脸、白皮肤等组合处理,如果这些功能的每个组合都写一个类进行实现的话那么代码就变得很多、很死、很臭。这时如果每个小的功能做成一个类,每个类的输入和输出都解耦,然后运行时根据需要组合成链表,这样更加灵活。
- 装饰模式面向「运行时」的「对象实例」,这些对象可以根据需要进行任意组合改变消息处理流程,从而达到优雅解决问题的目的
- 经典运用装饰模式的例子是 Java I/O Streams 框架
使用方法
调用者
class Client {
public static void main(String[] args){
// one component
Component component = new ConcreteComponent();
// decor component with decorator
Component decorator = new ConcreteDecorator(component);
// send msg to decorator
decorator.operation();
}
}
内部实现
interface Component{
void operation();
}
class ConcreteComponent implements Component {
void operation(){
// to sth.
}
}
class ConcreteDecorator implements Component {
Component component;
ConcreteDecorator(Component component){
this.component = component;
}
void operation(){
// do sth. before
component.operation();
// do sth. after
}
}
练习题
- Android Framework 层 Decorator/Wrapper 的经典实现(通过关键字搜索出相应模块)
- ContextWrapper 类图
- DrawableWrapper 类图
- Java I/O Streams 类图
- 字节流、字符流
- 缓冲、格式化能力
总结
- 从数据结构角度考虑,Decorator/Wrapper 模式是经常被使用的模式,因为每一小块的数据总会被大块的数据结构包裹起来(挂到大块的数据内部)。最经典的例子就是网络层的数据组装和拆卸。
参考
[1] 装饰模式