Decorator(装饰) — 对象结构型模式
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。
适用场景
- 在不影响其他对象的情况下,以动态,透明的方式给单个对象添加职责。
- 处理那些可以撤销的职责。
- 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能类定义被隐藏,或类定义不能用于生成子类。
UML 图
效果
- 比静态继承更灵活
- 避免在层次结构高层的类有太多的特征:Decorator 模式提供了一种“即用即付” 的方法来添加职责。它并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反,你可以定义一个简单的类,并且用 Decorator 类给它逐渐地添加功能。
- Decorator 与它的 Component 不一样,Decorator 虽然是一个透明的包装,但我们从对象标识的观点出发,一个被装饰了的组件与这个组件是有差别的,因此,使用装饰时不应该依赖对象标识。
实现
使用 Decorator 模式时应注意以下几点:
- 接口的一致性:装饰对象的接口必须与它所装饰的 Component 的接口是一致的,所有的 ConcreteDecorator类必须有一个公共的父类。(至少在C++中如此)
- 保持 Component 类的简单性:为了保证接口的一致性,组件和装饰必须有一个公共的 Component 父类。因此保持这个类的简单性是很重要的,即它应集中于定义接口而不是存储数据。对数据表示的定义应延迟到子类中,否则 Component 类会变得过于复杂和庞大,因而难以大量使用。
- 改变对象外壳与改变对象内核:Decorator可以看做是一个对象的外壳,它可以改变这个对象的行为。另一种方法是改变对象的内核,即 Strategy 模式。
当 Component 类原本就很庞大时,使用 Decorator 模式代价太高,Strategy 模式相对好一些。在 Strategy 模式中,组件将它的一些行为转发给一个独立的策略对象,我们可以替换策略对象,从而改变或扩充组件的功能。
实现略。