1 意图
动态地给一个对象添加一些额外的职责。
2 别名
包装器 Wrapper
3 动机
希望给某个对象而不是整个类添加一些功能。如图形界面添加一些特性(边框,滚动等)。
- 使用继承机制是以一种有效途径,然而不够灵活;
- 将组件嵌入另一个对象,有这个对象添加特性,该嵌入的对象称为装饰。该装饰与所装饰的组件接口一致,故对其透明。
4 适用性
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤消的职责。
- 当不能采用生成子类的方法进行扩充时。
- 一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。
- 另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
5 结构
6 参与者
- Component(VisualComponent)
- 定义一个对象接口,可以给这些对象动态地添加职责。
- ConcreteComponent(TextView)
- 定义一个对象,可以给这个对象添加一些职责。
- Decorator
- 维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
- ConcreteDecorator(BorderDecorator,ScrollDecorator)
- 向组件添加职责。
7 协作
Decorator 将请求转发给它的 Component 对象,并有可能在转发请求前后执行一些附加的
动作。
8 效果
- 优点:
- 比静态继承更灵活
- 避免在层次结构高层的类有太多的特征
- 缺点:
- Decorator 与 Component 不同,故使用 Decorator 不应该依赖 Component
- 有许多小对象
9 实现
- 接口的一致性;
- 省略抽象的 Decorator 类,仅需要一个职责时;
- 保存 Component 类的简单性;
- 改变对象外壳(Strategy 策略模式可改变对象内核)
注:
当 Component 类原本很庞大时,使用 Decorator 模式代价太大,可考虑使用 Strategy 模式。
10 代码示例
Component
1
2
3
4class Component
{
public abstract void Operation();
}ConcreteComponent
1
2
3
4
5
6
7class ConcreteComponent:Component
{
public override void Operation()
{
Console.WriteLine("ConcreteComponent");
}
}BaseDecorator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class BaseDecorator:Component
{
private Component component;
public BaseDecorator(Component component)
{
this.component = component;
}
public override void Operation()
{
if(component!=null)
{
component.Operation();
}
}
}ConcreteDecorator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class ConcreteDecorator:BaseDecorator
{
public ConcreteDecorator(Component component)
:base(component)
{
}
public override void Operation()
{
base.Operation();
this.Draw();
}
private void Draw()
{
Console.WriteLine("ConcreteDecorator");
}
}Client
1
2
3
4
5
6
7
8
9
10
11class Client
{
public static void Main(string[] args)
{
Component component=new ConcreteComponent();
component.Operation();
BaseDecorator decorator=new ConcreteDecorator(component);
decorator.Operation();
}
}
11 已知应用
用户界面工具,Stream。
12 相关模式
- Adapter 模式:Decorator 模式不同于 Adapter 模式,因为装饰仅改变对象的职责而不改
变它的接口;而适配器将给对象一个全新的接口。 - Composite 模式:可以将装饰视为一个退化的、仅有一个组件的组合。然而,装饰仅
给对象添加一些额外的职责—它的目的不在于对象聚集。 - Strategy 模式:用一个装饰你可以改变对象的外表;而Strategy模式使得你可以改变
对象的内核。这是改变对象的两种途径。