访问者模式
【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 */
【3】访问者模式角色分析
在访问者模式中,主要包括下面几个角色:
抽象访问者:一般为抽象类或者接口(如上例Action),声明访问者可以访问哪类元素。
具体到程序中就是visit方法中的参数定义哪些类型的元素是可以被访问的。
访问者:实现抽象访问者所声明的方法(如上例Success,Love),它影响到访问者具体访问到一种元素后该干什么,要做什么事情。
抽象元素类(被访问者):一般为抽象类或者接口(如上例Person),声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的。
抽象元素一般有两类方法,一部分是本身的业务逻辑,另外就是允许接收哪类访问者来访问。
元素类(被访问者):实现抽象元素类所声明的accept方法(如上例Man,Woman),通常都是以this指针为实参,基本上已经形成一种定式。
元素对象(被访问者)容器:一个元素的容器(如上例ObjectStructure),一般包含一个容纳多个不同类、不同接口的容器,如List、Set、Map等,在项目中一般很少抽象出这个角色。
【4】访问者模式总结
应用情景:访问者模式适用于数据结构稳定的系统。实质上把数据结构和作用于数据结构上的操作分离开。
因为访问者模式使得算法操作增加变得更容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。
优点:新增加操作很容易,因为新增加操作相当于增加一个访问者。
由以上示例可以得知:访问者模式将有限的行为操作(访问者)集中到有限个数据结构(访问者)对象上。
比如,我们现在需求再增加一个“失败”的操作。只需要继承自Action再实现一个所谓的 “失败” 访问者即可。
Good Good Study, Day Day Up.
顺序 选择 循环 总结