访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
下面是访问者模式的UML图:
/*
* Copyright (c) 2018 initm.com All rights reserved.
* 作者: Stupid
* 描述: 访问者模式
* 完成时间: 2018-1-15 22:33
*/
#include <QCoreApplication>
#include <iostream>
#include <cstdlib>
#include <typeinfo>
#include <list>
class ConcreteElementA;
class ConcreteElementB;
class Visitor{
public:
virtual void VisitConcreteElementA(ConcreteElementA* concreteElementA) = 0;
virtual void VisitConcreteElementB(ConcreteElementB* concreteElementB) = 0;
};
template <int N>
class ConcreteVisitor: public Visitor{
public:
void VisitConcreteElementA(ConcreteElementA* concreteElementA){
std::cout << typeid(concreteElementA).name() << "被" << typeid(this).name() << "访问" << std::endl;
}
void VisitConcreteElementB(ConcreteElementB* concreteElementB){
std::cout << typeid(concreteElementB).name() << "被" << typeid(this).name() << "访问" << std::endl;
}
};
class Element{
public:
virtual void Accept(Visitor* visitor) = 0;
virtual ~Element(){;}
};
class ConcreteElementA: public Element{
public:
void Accept(Visitor* visitor)override final{
visitor->VisitConcreteElementA(this);
}
void OperatorA(){
;//其他相关操作
}
};
class ConcreteElementB: public Element{
public:
void Accept(Visitor* visitor)override final{
visitor->VisitConcreteElementB(this);
}
void OperatorB(){
;//其他相关操作
}
};
class ObjectStructure{
private:
std::list<Element*> elements;
public:
void Attach(Element* element){
elements.push_back(element);
}
void Detach(Element* element){
for (std::list<Element*>::iterator it = elements.begin(); it != elements.end(); it++){
if(*it == element){
elements.erase(it);
delete element;
}
}
}
void Accept(Visitor* visitor){
for (auto index : elements){
index->Accept(visitor);
}
}
};
int main(int argc, char *argv[])
{
system("chcp 65001");
QCoreApplication a(argc, argv);
ObjectStructure* o = new ObjectStructure;
o->Attach(new ConcreteElementA());
o->Attach(new ConcreteElementB());
ConcreteVisitor<1>* v1 = new ConcreteVisitor<1>;
ConcreteVisitor<2>* v2 = new ConcreteVisitor<2>;
o->Accept(v1);
o->Accept(v2);
return a.exec();
}