访问者模式

访问者模式定义

访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

访问者模式结构图

访问者模式结构图如下所示:

图 01 访问者模式结构图

访问者模式套用代码

  1 #include "iostream"
  2 using namespace std;
  3 #include <string>
  4 #include <list>
  5 
  6 class ConcreteElementA;
  7 class ConcreteElementB;
  8 // 访问者抽象类
  9 class Visitor
 10 {
 11 public:
 12     virtual void VisitConcreteElementA(ConcreteElementA* concreteElementA) = 0;
 13     virtual void VisitConcreteElementB(ConcreteElementB* concreteElementB) = 0;
 14 };
 15 
 16 // 具体访问者1
 17 class ConcreteVisitor1 : public Visitor
 18 {
 19 public:
 20     virtual void VisitConcreteElementA(ConcreteElementA* concreteElementA)
 21     {
 22         cout << "ConcreteVisitor1 : VisitConcreteElementA : ConcreteElementA" << endl;
 23     }
 24 
 25     virtual void VisitConcreteElementB(ConcreteElementB* concreteElementB)
 26     {
 27         cout << "ConcreteVisitor1 : VisitConcreteElementB : ConcreteElementB" << endl;
 28     }
 29 };
 30 
 31 // 具体访问者2
 32 class ConcreteVisitor2 : public Visitor
 33 {
 34 public:
 35     virtual void VisitConcreteElementA(ConcreteElementA* concreteElementA)
 36     {
 37         cout << "ConcreteVisitor2 : VisitConcreteElementA : ConcreteElementA" << endl;
 38     }
 39 
 40     virtual void VisitConcreteElementB(ConcreteElementB* concreteElementB)
 41     {
 42         cout << "ConcreteVisitor2 : VisitConcreteElementB : ConcreteElementB" << endl;
 43     }
 44 };
 45 
 46 class Element
 47 {
 48 public:
 49     virtual void Accept(Visitor* visitor) = 0;
 50 };
 51 
 52 
 53 class ConcreteElementA : public Element
 54 {
 55 public:
 56     virtual void Accept(Visitor* visitor)
 57     {
 58         // 利用双分派技术,实现处理与数据结构的分离
 59         visitor->VisitConcreteElementA(this);
 60     }
 61 
 62     // 其他的相关方法
 63     void OperationA()
 64     {
 65     
 66     }
 67 };
 68 
 69 class ConcreteElementB : public Element
 70 {
 71 public:
 72     virtual void Accept(Visitor* visitor)
 73     {
 74         // 利用双分派技术,实现处理与数据结构的分离
 75         visitor->VisitConcreteElementB(this);
 76     }
 77 
 78     // 其他的相关方法
 79     void OperationB()
 80     {
 81     
 82     }
 83 };
 84 
 85 class ObjectStructure
 86 {
 87 private:
 88     list<Element*> elements;
 89 public:
 90     void Attach(Element* element)
 91     {
 92         elements.push_back(element);
 93     }
 94 
 95     void Detach(Element* element)
 96     {
 97         for(list<Person*>::iterator iter=elements.begin();iter!=elements.end();++iter)
 98         {
 99             if((*iter)==element)
100             {
101                 elements.erase(iter);
102             }
103         }
104     }
105 
106     void Accept(Visitor* visitor)
107     {
108         list<Element*>::iterator it = elements.begin();
109         while(it != elements.end())
110         {
111             (*it)->Accept(visitor);
112             it++;
113         }
114     }
115 };
116 
117 void main()
118 {
119     ObjectStructure* o = new ObjectStructure();
120     ConcreteElementA* ce1 = new ConcreteElementA();
121     ConcreteElementB* ce2 = new ConcreteElementB();
122     o->Attach(ce1);
123     o->Attach(ce2);
124 
125     ConcreteVisitor1* v1 = new ConcreteVisitor1();
126     ConcreteVisitor2* v2 = new ConcreteVisitor2();
127 
128     o->Accept(v1);
129     o->Accept(v2);
130     
131     delete o;
132     o = NULL;
133 
134     delete ce1;
135     ce1 = NULL;
136 
137     delete ce2;
138     ce2 = NULL;
139 
140     delete v1;
141     v1 = NULL;
142 
143     delete v2;
144     v2 = NULL;
145 }

访问者模式特点

① 在这里,Element就是我们‘人’类,而ConcreteElementA和ConcreteElementB就是‘男人’和‘女人’,Visitor就是我们写的‘状态’类,具体的ConcreteVisitor就是那些‘成功’、‘失败’、‘恋爱’等等状态。至于ObjectStructure就是‘对象结构’类了

② 访问者模式适用于数据结构相对稳定的系统,把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化

③ 访问者模式的目的是要把处理从数据结构分离出来。很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式是比较合适的,因为访问者模式使得算法操作的增加变得容易。反之,如果这样的系统的数据结构对象易于变,经常要有新的数据对象增加进来,就不适合使用访问者模式

④ 访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中

⑤ 访问者模式的缺点就是使增加新的数据结构变得困难了

⑥ 大多时候你并不需要访问者模式,但当一旦你需要访问者模式时,那就是真的需要它了,事实上,我们很难找到数据结构不变化的情况,所以用访问者模式的机会也就不太多了

访问者模式实例应用

访问者模式实例应用类图

图 02 访问者模式实例应用类图

访问者模式实例应用代码

  1 #include <iostream>
  2 #include <list>
  3 #include <string>
  4 using namespace std;
  5  
  6 class CMan;
  7 class CWoman;
  8 
  9 // Visitor
 10 class CAction
 11 {
 12 public:
 13     virtual void GetManConclusion(CMan *) = 0;
 14     
 15     virtual void GetWomanConclusion(CWoman *) = 0;
 16     
 17     virtual ~CAction()
 18     {
 19     
 20     }
 21 }; 
 22 
 23 // 具体Visitor1
 24 class CSuccess : public CAction
 25 {
 26 
 27 public:
 28     virtual void GetManConclusion(CMan *)
 29     {
 30         cout << "男人成功时,背后多半有一个伟大的女人" << endl;
 31     }
 32 
 33     virtual void GetWomanConclusion(CWoman *)
 34     {
 35         cout << "女人成功时,背后多半有不成功的男人" << endl;
 36     }
 37 
 38     virtual ~CSuccess()
 39     {
 40     
 41     }
 42 };
 43 
 44 // 具体Visitor2
 45 class CLove : public CAction
 46 {
 47 public:
 48     virtual void GetManConclusion(CMan *)
 49     {
 50         cout << "男人恋爱时,凡事不懂装懂" << endl;
 51     }
 52     
 53     virtual void GetWomanConclusion(CWoman *)
 54     {
 55         cout << "女人恋爱时,凡事懂也装不懂" << endl;
 56     }
 57 
 58     virtual ~CLove()
 59     {
 60     
 61     }
 62 };
 63 
 64 // Element
 65 class CPerson
 66 {
 67 public:
 68     virtual void Accept(CAction*) = 0;
 69 
 70     virtual ~CPerson()
 71     {
 72     
 73     }
 74 };
 75 
 76 // 具体Element1
 77 class CMan : public CPerson
 78 {
 79 public:
 80     virtual void Accept(CAction* visitor)
 81     {
 82                 // 首先在客户程序中将具体状态作为参数传递给“男人”类完成了一次,
 83         // 然后“男人”类调用作为参数的“具体状态”中的方法“男人反应”,同时
 84         // 将自己(this)作为参数传递进去。这便完成了第二次分派
 85         visitor->GetManConclusion(this);
 86     }
 87 
 88     virtual ~CMan()
 89     {
 90     
 91     }
 92 };
 93 
 94 // 具体Element2
 95 class CWoman : public CPerson
 96 {
 97 public:
 98     virtual void Accept(CAction* visitor)
 99     {
100         // 首先在客户程序中将具体状态作为参数传递给“女人”类完成了一次,
101         // 然后“女人”类调用作为参数的“具体状态”中的方法“女人反应”,同时
102         // 将自己(this)作为参数传递进去。这便完成了第二次分派
103         visitor->GetWomanConclusion(this);
104     }
105 
106     virtual ~CWoman()
107     {
108     
109     }
110 };
111 
112 class CObjectStructure
113 {
114 private:
115     list<CPerson*> elements;
116 public:
117     void Attach(CPerson* element)
118     {
119         elements.push_back(element);
120     }
121 
122     void Detach(CPerson* element)
123     {
124         for(list<CPerson*>::iterator iter=elements.begin();iter!=elements.end();++iter)
125         {
126             if((*iter)==element)
127             {
128                 elements.erase(iter);
129             }
130         }
131     }
132 
133     void Display(CAction *visitor)
134     {
135         for(list<CPerson*>::iterator iter=elements.begin();iter!=elements.end();++iter)
136         {
137             (*iter)->Accept(visitor);
138         }
139     }
140 
141     virtual ~CObjectStructure()
142     {
143     
144     }
145 };
146 
147 void main()
148 {
149     CObjectStructure* os = new CObjectStructure();
150     CWoman* w = new CWoman();
151     os->Attach(w);
152 
153     CSuccess *s=new CSuccess();
154     os->Display(s);
155 
156     CLove *lv=new CLove();
157     os->Display(lv);
158 
159     delete os;
160     os = NULL;
161     delete w;
162     w = NULL;
163     delete s;
164     s = NULL;
165     delete lv;
166     lv = NULL;
167 }

2014-12-09    20:50:44

 

posted on 2014-12-09 20:47  xiaoheike  阅读(285)  评论(0)    收藏  举报

导航