装饰模式

装饰模式定义

装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

装饰模式使用情况

1. 需要扩展一个类的功能,或给一个类添加附加职责。

2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

装饰模式结构图

装饰模式类图

图 01 装饰模式类图

装饰模式套用代码

由于装饰模式有点复杂附上套用代码,本文的下一部分有具体的实现代码。

  1 #include "iostream"
  2 using namespace std;
  3 // Component类
  4 class Component
  5 {
  6 public:
  7     virtual void Operation()
  8     {
  9 
 10     }
 11 };
 12 
 13 // ConcreteComponent类 
 14 class ConcreteComponent : public Component
 15 {
 16 public:
 17     virtual void Operation()
 18     {
 19         cout << "具体对象的操作" <<endl;
 20     }
 21 };
 22 
 23 // Decorator类 
 24 class Decorator : public Component
 25 {
 26 protected:
 27     Component* component;
 28 public:
 29     void SetComponent(Component* component)
 30     {
 31         this->component = component;
 32     }
 33 
 34     virtual void Operation()
 35     {
 36         if(component != NULL)
 37         {
 38             component->Operation();
 39         }
 40     }
 41 };
 42 
 43 // ConcreteDecoratorA类
 44 class ConcreteDecoratorA : public Decorator
 45 {
 46 private:
 47     string addedState;
 48 public:
 49     void Operation()
 50     {
 51         // 调用父类的Operation
 52         Decorator::Operation();
 53         addedState = "New State";
 54         cout << "具体装饰对象A的操作" << endl;
 55     }
 56 };
 57 
 58 // ConcreteDecoratorB类 
 59 class ConcreteDecoratorB : public Decorator
 60 {
 61 public:
 62     virtual void Operation()
 63     {
 64         // 调用父类的Operation
 65         Decorator::Operation();
 66         AddedBehavior();
 67         cout << "具体装饰对象B的操作" << endl;
 68     }
 69     
 70 private:
 71     void AddedBehavior()
 72     {
 73     
 74     }
 75 };
 76 
 77 
 78 void main()
 79 {
 80     ConcreteComponent* c = new ConcreteComponent();
 81     ConcreteDecoratorA* d1 = new ConcreteDecoratorA();
 82     ConcreteDecoratorB* d2 = new ConcreteDecoratorB();
 83 
 84     d1->SetComponent(c);
 85     d2->SetComponent(d1);
 86     d2->Operation();
 87     
 88     if(c != NULL)
 89     {
 90         delete c;
 91         c = NULL;
 92     }
 93     
 94     if(d1 != NULL)
 95     {
 96         delete d1;
 97         d1 = NULL;
 98     }
 99 
100     if(d2 != NULL)
101     {
102         delete d2;
103         d2 = NULL;
104     }
105     cout << endl;
106 }

装饰模式实例应用

装饰模式实例类图

一个人的穿着,根据不同的要求有不同的装扮,为了简单我这边只编写了T-Shirt类和BigTrouser类,这个将典型装饰模式的ConcreteComponent类,如果要使用这个类,那么这个类只是继承CPenson类,不用添加任何的变量以及方法,所以这边就省去这个类了。

具体实例的类图如下,图 02所示:

image

图 02 装饰模式实例类图

具体实例的代码

 1 #include "iostream"
 2 using namespace std;
 3 #include <string>
 4 
 5 class CPerson
 6 {
 7 private:
 8     string m_name;
 9 public:
10     CPerson()
11     {
12     
13     }
14     CPerson(string name)
15     {
16         this->m_name = name;
17     }
18 
19     virtual void Show()
20     {
21         cout << "装扮的 " << m_name << endl;
22     }
23 
24     virtual ~CPerson()
25     {
26     
27     }
28 };
29 
30 class CFinery : public CPerson
31 {
32 protected:
33     CPerson* m_component;
34 public:
35     void Decorate(CPerson* component)
36     {
37         this->m_component = component;
38     }
39     
40     virtual void Show()
41     {
42         if(this->m_component != NULL)
43         {
44             // 多态
45             m_component->Show();
46         }
47     }
48 
49     virtual ~CFinery()
50     {
51     
52     }
53 };
54 
55 class CTShirt : public CFinery
56 {
57 public:
58     virtual void Show()
59     {    
60         cout << "T-Shirt ";
61         // 多态,不调用Finery.Show()
62         m_component->Show(); //CFinery::Show(); 会调用Finery.Show()
63     }
64 
65     virtual ~CTShirt()
66     {
67     
68     }
69 };
70 
71 class CBigTrouser : public CFinery
72 {
73 public:
74     virtual void Show()
75     {
76         cout << "BigTrouser ";
77         // 多态,不调用Finery.Show()
78         m_component->Show();//CFinery::Show(); 会调用Finery.Show()
79     }
80 };
81 
82 void main()
83 {
84     CPerson* person = new CPerson("a");
85     CTShirt* ts = new CTShirt();
86     CBigTrouser* bt = new CBigTrouser();
87 
88     // 这边有点绕,画个图理解一下
89     ts->Decorate(person);
90     bt->Decorate(ts);
91     bt->Show();
92     
93     // 内存一定要释放
94     delete person;
95     delete ts;
96     delete bt;
97 }

创建CTShirt 对象实例拥有的方法与属性

图 03 创建CTShirt 对象实例拥有的方法与属性

装饰模式的特点

(1) 装饰对象(CFinery)和真实对象(CTShirt与CBigTrouser)有相同的接口(Show)。这样客户端对象(main中创建的对象)就能以和真实对象相同的方式和装饰对象交互

(2) 装饰对象(CFinery)包含一个真实对象的引用(CPerson* m_component)

(3) 装饰对象(CFinery)接受所有来自客户端的请求。它把这些请求转发给真实的对象(CTShirt与CBigTrouser)

(4) 装饰对象(CFinery)可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

2014-11-25 21:01:48

posted on 2014-11-25 21:00  xiaoheike  阅读(184)  评论(0)    收藏  举报

导航