设计模式之装饰模式
装饰模式,动态地给一个对象添加一些额外的职责(不一定重要的功能,只是偶然一次执行),就增加功能来说,装饰模式比生成子类更为灵活。其UML图如下:
ConcreteComponent定义了一个具体的对象,ConcreteDecorator类是用来装饰ConcreteComponent的。在Decorator类内由一个Component的引用实际是指向ConcreteComponent的。一旦一个装饰类装饰了一个组件,则该装饰类即代表了该组件,因为它们都有相同的基类,并且所有的装饰类都有相同的基类,所以可以连续不断的装饰下去。
示例代码如下:
1 // DecoratorModle.h文件
2 #pragma once
3
4 #include <iostream>
5 // 基础类
6 class Component
7 {
8 public:
9 virtual void Operation()
10 {
11 std::cout << "被装饰者" << std::endl;
12 }
13 };
14
15 class ConcreteComponent : public Component
16 {
17 public:
18 virtual void Operation()
19 {
20 std::cout << "具体被装饰者" << std::endl;
21 }
22 };
23 // 装饰者
24 class Decorator : public Component
25 {
26 public:
27 void Decorate(Component * component)
28 {
29 m_pComponent = component;
30 }
31 virtual void Operation()
32 {
33 m_pComponent->Operation();
34 }
35 protected:
36 Component * m_pComponent;
37 };
38 // 装饰者A
39 class Decorator_A : public Decorator
40 {
41 public:
42 virtual void Operation()
43 {
44 std::cout << "装饰者A" << std::endl;
45 m_pComponent->Operation();
46 }
47 };
48 // 装饰者B
49 class Decorator_B : public Decorator
50 {
51 public:
52 virtual void Operation()
53 {
54 std::cout << "装饰者B" << std::endl;
55 m_pComponent->Operation();
56 }
57 };
测试代码如下:
1 #include <iostream>
2 #include "DecoratorModel.h"
3
4 int main()
5 {
6 using namespace std;
7 // 装饰者模式
8 // 被装饰者
9 Component * p = new ConcreteComponent();
10 Decorator * pDecorator_A = new Decorator_A();
11 Decorator * pDecorator_B = new Decorator_B();
12 // pDecorator_A(装饰类A)装饰了p(具体组件)
13 pDecorator_A->Decorate(p);
14 // 因为pDecorator_A 装饰了p,所以p_Decorator_A代表p
15 // 这里其实是pDecorator_B又装饰了p
16 pDecorator_B->Decorate(pDecorator_A);
17
18 pDecorator_B->Operation();
19 delete pDecorator_B;
20 delete pDecorator_A;
21 delete p;
22
23 getchar();
24 return 0;
25 }
测试结果如下:
装饰模式在装饰模式中只能根根据需求按顺序装饰起来,一个Decorator对象只能装饰一个具体组件一次,切忌不能循环装饰。
装饰模式是为已有功能动态地添加更多的一种方式。当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为,它们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主要类的复杂度,而这些新加入的东西仅仅是为了满足一些某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类种,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时更具需要有选择地、按顺序地使用装饰功能包装对象了。其优点是把类种的装饰功能从类种搬移去除,这样可以简化原有的类。这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类种重复的装饰逻辑。