访问者模式
访问者模式定义
访问者模式(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
浙公网安备 33010602011771号