访问者模式

【1】什么是访问者模式?

今天学习访问者模式,访问者模式是A对象访问B对象的一种模式。非也。

那么,何谓访问者模式呢?真难理解!因为这个名字就TMD超晦涩,让人听不懂,或许只是此名称本身有且仅有的一个抽象意义而已。

何谓抽象意义呢?如果你理解了《类的概念》大概你才会有所参透。

我一直理解:抽象是多态的爸爸。怎么解释呢?你想想:

类都是超级抽象的,而经由父类(即基类)衍生的子类(即派生类)就是 “多态” 的全部内在意义。

访问者模式,其实没那么复杂(呵呵!或许窃理解有误)。模式即一种做法,所以一句话概述:

把数据信息和操作行为各自分开处理而不放在一坨的做法。(要不,谁访问谁呀?你先琢磨琢磨。)

【2】访问者模式代码示例:

代码示例1(一般写法):

 1 #include <iostream>
 2 #include <list>
 3 #include <string>
 4 using namespace std;
 5 
 6 class Person
 7 {
 8 public:
 9     string action;
10     virtual void getConclusion() = 0;
11 };
12 
13 class Man : public Person
14 {
15 public:
16     void getConclusion()
17     {
18         if (action == "成功")
19         {
20             cout << "男人成功时,背后多半有一个伟大的女人。" << endl;
21         }
22         else if (action == "恋爱")
23         {
24             cout << "男人恋爱时,凡事不懂装懂。" << endl;
25         }
26     }
27 };
28 
29 class Woman : public Person
30 {
31 public:
32     void getConclusion()
33     {
34         if (action == "成功")
35         {
36             cout << "女人成功时,背后多半有失败的男人。" << endl;
37         }
38         else if (action == "恋爱")
39         {
40             cout << "女人恋爱时,遇到事懂也装不懂。" << endl;
41         }
42     }
43 };
44 
45 void main()
46 {
47     list<Person*> persons;
48 
49     Person *pMan1 = new Man();
50     pMan1->action = "成功";
51     persons.push_back(pMan1);
52 
53     Person *pWoman1 = new Woman();
54     pWoman1->action = "成功";
55     persons.push_back(pWoman1);
56 
57     Person *pMan2 = new Man();
58     pMan2->action = "恋爱";
59     persons.push_back(pMan2);
60 
61     Person *pWoman2 = new Woman();
62     pWoman2->action = "恋爱";
63     persons.push_back(pWoman2);
64 
65     list<Person*>::iterator iter = persons.begin();
66     while (iter != persons.end())
67     {
68         (*iter++)->getConclusion();
69     }
70 }
71 //Result:
72 /*
73 男人成功时,背后多半有一个伟大的女人。
74 女人成功时,背后多半有失败的男人。
75 男人恋爱时,凡事不懂装懂。
76 女人恋爱时,遇到事懂也装不懂。
77 */

代码示例2(访问者模式写法):

  1 #include <iostream>
  2 #include <list>
  3 #include <string>
  4 using namespace std;
  5  
  6 class Man;
  7 class Woman;
  8 
  9 class Action
 10 {
 11 public:
 12     virtual void getManConclusion(Man *) = 0;
 13     virtual void getWomanConclusion(Woman *) = 0;
 14 }; 
 15 
 16 class Success : public Action
 17 {
 18     void getManConclusion(Man *)
 19     {
 20         cout << "男人成功时,背后多半有一个伟大的女人" << endl;
 21     }
 22     void getWomanConclusion(Woman *)
 23     {
 24         cout << "女人成功时,背后多半有不成功的男人" << endl;
 25     }
 26 
 27 };
 28 
 29 class Love : public Action
 30 {
 31     void getManConclusion(Man *)
 32     {
 33         cout << "男人恋爱时,凡事不懂装懂" << endl;
 34     }
 35     void getWomanConclusion(Woman *)
 36     {
 37         cout << "女人恋爱时,凡事懂也装不懂" << endl;
 38     }
 39 };
 40 
 41 class Person
 42 {
 43 public:
 44     virtual void accept(Action*) = 0;
 45 };
 46 
 47 class Man : public Person
 48 {
 49 public:
 50     void accept(Action* visitor)
 51     {
 52         visitor->getManConclusion(this);
 53     }
 54 };
 55 
 56 class Woman : public Person
 57 {
 58 public:
 59     void accept(Action* visitor)
 60     {
 61         visitor->getWomanConclusion(this);
 62     }
 63 };
 64 
 65 class ObjectStructure
 66 {
 67 private:
 68     list<Person*> elements;
 69 
 70 public:
 71     void attach(Person* element)
 72     {
 73         elements.push_back(element);
 74     }
 75     void detach(Person* element)
 76     {
 77         for (list<Person*>::iterator iter = elements.begin(); iter != elements.end(); ++iter)
 78         {
 79             if ((*iter) == element)
 80             {
 81                 elements.erase(iter);
 82             }
 83         }
 84     }
 85     void display(Action *visitor)
 86     {
 87         for (list<Person*>::iterator iter = elements.begin(); iter != elements.end(); ++iter)
 88         {
 89             (*iter)->accept(visitor);
 90         }
 91     }
 92 };
 93 
 94 int main()
 95 {
 96     ObjectStructure objStructure;
 97     Success *os = new Success();
 98     Love *lv = new Love();
 99 
100     Person *man = new Man();
101     objStructure.attach(man);
102      
103     Person *woman = new Woman();
104     objStructure.attach(woman);
105 
106     objStructure.display(os);
107     objStructure.display(lv);
108 
109     return 0;
110 }
111 //Result:
112 /*
113 男人成功时,背后多半有一个伟大的女人
114 女人成功时,背后多半有不成功的男人
115 男人恋爱时,凡事不懂装懂
116 女人恋爱时,凡事懂也装不懂
117 */
View Code

 【3】访问者模式角色分析

在访问者模式中,主要包括下面几个角色:

抽象访问者:一般为抽象类或者接口(如上例Action),声明访问者可以访问哪类元素。

      具体到程序中就是visit方法中的参数定义哪些类型的元素是可以被访问的。

访问者:实现抽象访问者所声明的方法(如上例Success,Love),它影响到访问者具体访问到一种元素后该干什么,要做什么事情。

抽象元素类(被访问者):一般为抽象类或者接口(如上例Person),声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的。

      抽象元素一般有两类方法,一部分是本身的业务逻辑,另外就是允许接收哪类访问者来访问。

元素类(被访问者):实现抽象元素类所声明的accept方法(如上例Man,Woman),通常都是以this指针为实参,基本上已经形成一种定式。

元素对象(被访问者)容器:一个元素的容器(如上例ObjectStructure),一般包含一个容纳多个不同类、不同接口的容器,如List、Set、Map等,在项目中一般很少抽象出这个角色。

【4】访问者模式总结

应用情景:访问者模式适用于数据结构稳定的系统。实质上把数据结构和作用于数据结构上的操作分离开。

因为访问者模式使得算法操作增加变得更容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。

优点:新增加操作很容易,因为新增加操作相当于增加一个访问者。

由以上示例可以得知:访问者模式将有限的行为操作(访问者)集中到有限个数据结构(访问者)对象上。

比如,我们现在需求再增加一个“失败”的操作。只需要继承自Action再实现一个所谓的 “失败” 访问者即可。

 

Good  Good   Study,  Day  Day   Up.

顺序  选择   循环  总结

posted @ 2014-09-04 22:34  kaizenly  阅读(1273)  评论(0编辑  收藏  举报
打赏