Decorator

装饰者

动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

适用性

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

结构

Decorator Class 1
Decoratot Class 2

Component - 定义一个对象接口,可以给这些对象动态地添加职责。
ConcreteComponent - 定义一个对象,可以给这个对象添加一些职责。
Decorator - 维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
ConcreteDecorator - 向组件添加职责。

协作:
Decorator将请求转发给它的Component对象,并有可能在转发请求前后执行一些附加的动作。

示例情境

有多种不同的咖啡,而每种咖啡又有多种加调料的方式。
Decorator Scenario

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
//---------------------------------------------------
class Component
{
public:
virtual void methodA(){}
virtual void methodB(){}
};
//---------------------------------------------------
class ConcreteComponent : public Component
{
public:
virtual void methodA()
{

std::cout<<"I'm methodA from ConcreteComponent."<<std::endl;
}
virtual void methodB()
{

std::cout<<"I'm methodB from ConcreteComponent."<<std::endl;
}
};
//---------------------------------------------------
class Decorator : public Component
{};
//---------------------------------------------------
class ConcreteDecoratorA : public Decorator
{
public:
ConcreteDecoratorA(Component* comp): Decorator(), m_component(comp){}
virtual void methodA()
{

if (!m_component) return;
std::cout<<"I'm methodA called from ConcreteDecoratorA: "<<std::endl;
m_component->methodA();
}
virtual void methodB()
{

if (!m_component) return;
std::cout<<"I'm methodA called from ConcreteDecoratorB: "<<std::endl;
m_component->methodA();
}
protected:
Component* m_component;
};
//---------------------------------------------------
class ConcreteDecoratorB : public Decorator
{
public:
ConcreteDecoratorB(Component* comp): Decorator(), m_component(comp){}
virtual void methodA()
{

if (!m_component) return;
std::cout<<"I'm methodA called from ConcreteDecoratorB: "<<std::endl;
m_component->methodA();
}
virtual void methodB()
{

if (!m_component) return;
std::cout<<"I'm methodA called from ConcreteDecoratorB: "<<std::endl;
m_component->methodA();
}
protected:
Component* m_component;
};
//---------------------------------------------------
int main()
{

Component* product_type = new ConcreteComponent();
Component* product = new ConcreteDecoratorA(product_type);
product->methodA();
product->methodB();
system("Pause");
}

相关模式

  • Adapter模式:Decorator模式不同于Adapter模式,因为装饰仅改变对象的职责而不改变它的接口;而适配器将给对象一个全新的接口。
  • Composite模式:可以将装饰视为一个退化的、仅有一个组件的组合。然而,装饰仅给对象添加一些额外的职责——它的目的不在于对象聚集。
  • Strategy模式:用一个装饰你可以改变对象的外表;而Strategy模式使得你可以改变对象的内核。这是改变对象的两种途径。

[1] 设计模式:可复用面向对象软件的基础
[2] Head First 设计模式