设计模式探秘-22-访问者模式

访问者模式的学习与实践

模式定义

封装一些作用于某种数据结构中的各元素的操作,可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

类图

  1. Visitor 抽象访问者 抽象类或者接口,声明访问者可以访问的元素。具体到程序中即visit方法的参数定义哪些对象是可以被访问的。
  2. ConcreteVisitor 具体访问者 影响访问者访问到一个类后该怎么干,要做什么事情。
  3. Element 抽象元素 接口或者抽象类,声明接受哪一类访问者访问,程序上通过accept方法中的参数定义。
  4. ConcreateElement 具体元素 实现accept方法,通常是visitor.visit(this) 基本上形成了一个模式。
  5. ObjectStruture 结构对象 元素产生者,一般容纳多个不同类、不同接口的容器。项目中很少抽象出该角色。

优点

  1. 符合单一职责原则
  2. 优秀的扩展性
  3. 灵活性非常高

缺点

  1. 具体元素对访问者公布细节
  2. 具体元素变更比较困难
  3. 违背依赖倒置原则

使用场景

业务规则要求遍历多个不同对象。

注意事项

扩展

  1. 统计功能
  2. 多个访问者

实践

简单实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <iostream>

using namespace std;

//访问者模式
class ConcreteElementA;
class ConcreteElementB;
class Element;

class Visitor
{
public:
virtual ~Visitor()
{
}
virtual void VisitConcreteElementA(Element *elm) = 0;
virtual void VisitConcreteElementB(Element *elm) = 0;
protected:
Visitor()
{
}
};

class ConcreteVisitorA : public Visitor
{
public:
ConcreteVisitorA()
{
}
virtual ~ConcreteVisitorA()
{
}
virtual void VisitConcreteElementA(Element *elm)
{
cout<<__FUNCTION__<<" i will visit ConcreteElementA..."<<endl;
}
virtual void VisitConcreteElementB(Element *elm)
{
cout<<__FUNCTION__<<" i will visit ConcreteElementB..."<<endl;
}
};

class ConcreteVisitorB : public Visitor
{
public:
ConcreteVisitorB()
{
}
virtual ~ConcreteVisitorB()
{
}
virtual void VisitConcreteElementA(Element *elm)
{
cout<<__FUNCTION__<<" i will visit ConcreteElementA..."<<endl;
}
virtual void VisitConcreteElementB(Element *elm)
{
cout<<__FUNCTION__<<" i will visit ConcreteElementB..."<<endl;
}
};

class Element
{
public:
virtual ~Element()
{
}
virtual void Accept(Visitor *vis) = 0;
protected:
Element()
{
}
};

class ConcreteElementA : public Element
{
public:
ConcreteElementA()
{
}
~ConcreteElementA()
{
}
void Accept(Visitor *vis)
{
cout<<"visiting ConcreteElementA..."<<endl;
vis->VisitConcreteElementA(this);
}
};
class ConcreteElementB : public Element
{
public:
ConcreteElementB()
{
}
~ConcreteElementB()
{
}
void Accept(Visitor *vis)
{
cout<<"visiting ConcreteElementB..."<<endl;
vis->VisitConcreteElementB(this);
}
};

int main()
{
Visitor *visa = new ConcreteVisitorA();
Element *elma = new ConcreteElementA();
elma->Accept(visa);

Visitor *visb = new ConcreteVisitorB();
Element *elmb = new ConcreteElementB();
elmb->Accept(visb);
return 0;
}

参考资料

  1. 设计模式之禅
  2. GoF+23种设计模式解析