C++ 设计模式之访问者模式

发布时间 2023-07-07 14:00:45作者: 一杯清酒邀明月

设计模式之访问者模式
  访问者模式,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式适用于数据结构相对稳定的系统。它把数据结构和作用于结构上的操作之间耦合解脱开,使得操作几何可以相对自由地演化。访问者模式的目的使要把处理从数据结构中分离出来。很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的。

其UML图如下:

每个ConcreteVisitor都有自己的数据处理方式,但是它们处理的数据则是不变的。在ObjectStucture中有Element的列表,并提供了访问数据的接口。

示例代码如下:

  1 // VisitorModel.h文件
  2 #pragma once
  3 #include <iostream>
  4 #include <string>
  5 #include <vector>
  6 #include <algorithm>
  7 
  8 class Visitor;
  9 // 被访问元素
 10 class Element
 11 {
 12 protected: 
 13     std::string m_strName;
 14 public:
 15     Element(std::string str)
 16     {
 17         m_strName = str;
 18     }
 19     std::string getName()
 20     {
 21         return m_strName;
 22     }
 23     virtual void Accept(Visitor * visitor) = 0;
 24 };
 25 
 26 class ConcreteElementA : public Element
 27 {
 28 public:
 29     ConcreteElementA(std::string str) : Element(str) {}
 30     void Accept(Visitor * visitor);
 31 };
 32 
 33 class ConcreteElementB : public Element
 34 {
 35 public: 
 36     ConcreteElementB(std::string str) : Element(str) {}
 37     void Accept(Visitor * visitor);
 38 };
 39 
 40 // 访问者
 41 class Visitor
 42 {
 43 public:
 44     virtual void VisitConcreteElementA(ConcreteElementA * p) = 0;
 45     virtual void VisitConcreteElementB(ConcreteElementB * p) = 0;
 46 };
 47 
 48 class ConcreteVisitorA : public Visitor
 49 {
 50 public:
 51     void VisitConcreteElementA(ConcreteElementA * p)
 52     {
 53         std::cout << "ConcreteVisitorA 访问了" << p->getName() << std::endl;
 54     }
 55     void VisitConcreteElementB(ConcreteElementB * p)
 56     {
 57         std::cout << "ConcreteVisitorA 访问了" << p->getName() << std::endl;
 58     }
 59 };
 60 
 61 class ConcreteVisitorB : public Visitor
 62 {
 63 public:
 64     void VisitConcreteElementA(ConcreteElementA * p)
 65     {
 66         std::cout << "ConcreteVisitorB 访问了" << p->getName() << std::endl;
 67     }
 68     void VisitConcreteElementB(ConcreteElementB * p)
 69     {
 70         std::cout << "ConcreteVisitorB 访问了" << p->getName() << std::endl;
 71     }
 72 };
 73 
 74 void ConcreteElementA::Accept(Visitor * visitor)
 75 {
 76     visitor->VisitConcreteElementA(this);
 77 }
 78 void ConcreteElementB::Accept(Visitor * visitor)
 79 {
 80     visitor->VisitConcreteElementB(this);
 81 }
 82 // 聚集类
 83 class ObjectStructure
 84 {
 85 private:
 86     std::vector<Element *> m_vec;
 87 public:
 88     ~ObjectStructure()
 89     {
 90         for (auto it = m_vec.begin(); it != m_vec.end(); it++)
 91         {
 92             delete *it;
 93         }
 94         m_vec.clear();
 95     }
 96     void add(Element * p)
 97     {
 98         m_vec.push_back(p);
 99     }
100     void accept(Visitor * visitor)
101     {
102         for (auto it = m_vec.cbegin(); it != m_vec.cend(); it++)
103         {
104             (*it)->Accept(visitor);
105         }
106     }
107 };

测试代码如下:

 1 #include <iostream>
 2 #include "VisitorModel.h"
 3 
 4 int main()
 5 {
 6     using namespace std;
 7     // 访问者模式
 8     ObjectStructure * p = new ObjectStructure();
 9     p->add(new ConcreteElementA("A"));
10     p->add(new ConcreteElementB("B"));
11 
12     ConcreteVisitorA * pVisitorA = new ConcreteVisitorA();
13     ConcreteVisitorB * pVisitorB = new ConcreteVisitorB();
14 
15     p->accept(pVisitorA);
16     p->accept(pVisitorB);
17 
18     delete pVisitorA;
19     delete pVisitorB;
20     delete p;
21 
22     getchar();
23     return 0;
24 }

测试结果如下图:

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