4.4-Decorator「wrapper」-装饰器-结构型模式
目的
动态地向对象添加额外功能,比创建子类更加灵活
示例
GUI 工具箱允许你对任意一个用户界面组件添加一些特性(例如边框),或是一些行为(例如窗口滚动)。
一种较为灵活的方式是将组件嵌入另一个对象中,由这个对象添加边框。我们称这个嵌入的对象为装饰。
- 这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明(因此可以递归地嵌套)
- 它将客户请求转发给该组件,并且可能在转发前后执行一些额外的动作(例如画一个边框)。

适用性
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤销的职责。
- 当不能采用生成子类的方法进行扩充时,例如:
- 可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长
- 类定义被隐藏或类是 final 的
结构

- Component:对象接口
- ConcreteComponent
- Decorator:维护指向 Component 的指针,定义和 Component 一致的接口
- ConcreteDecorator:向组件添加职责(将操作代理给所持有的对象,并附加自身的操作)

优缺点
- 比静态继承更灵活:
- 可以用添加和分离装饰器的方法,用装饰在运行时增加和删除职责。
- 可以很容易地重复添加一个特性
- 避免在层次结构高层的类有太多的特征
- Decorator 相比 Component 模式而言,是完全透明的包装,使用装饰时不应当依赖对象标识
缺点:有许多小对象:采用 Decorator 模式进行系统设计往往会产生许多看上去类似的小对象,这些对象仅仅在它们相互连接的方式上有所不同,而不是它们的类或是它们的属性值有所不同。尽管对于那些了解这些系统的人来说,很容易对它们进行定制,但是很难学习这些系统,排错也很困难。
实现
- 接口一致性:装饰器必须和被装饰的对象接口一致
- 省略抽象的装饰器:仅需要添加一个职责时,没有必要定义抽象 Decorator 类
- 保持 Component 类的简单性:为保证一致性,组件和装饰器必须有共同的 Component 父类,因此需要避免这个类过大。这个父类应集中于定义接口而不是存储数据,对数据表示的定义应延迟到子类中
相关模式
- Adapter(4.1):Decorator 模式不同于 Adapter 模式,因为装饰仅改变对象的职责而不改变它的接口;而适配器将给对象一个全新的接口。
- Composite(4.3):可以将装饰视为一个退化的、仅有一个组件的组合。然而,装饰仅给对象添加一些额外的职责——它的目的不在于对象聚集。
装饰器 VS 策略模式
改变对象的行为主要有两种方式:
- Decorator 模式改变外壳
- Strategy 模式改变内核
当 Component 类原本就很庞大时,使用 Decorator 模式代价太高, Strategy 模式相对好一些













使用 Visitor 模式,必须定义两个类层次:


对象交互:
例如选择 ListBox 改变 EntryField 的内容


考虑需要撤销移动命令的情形:

