访问者模式是一种行为型模式
优点:
能够在不改变对象结构的情况下增加新的操作,使得操作集合可以相对独立地演化。
缺点:
- 增加新的元素类变得困难,因为每个新元素都必须被访问者类所接受。
- 此外,如果对象结构中的元素类经常发生变化,那么使用访问者模式可能不是最佳选择。
满足的设计原则:
访问者模式满足了开放封闭原则(Open-Closed Principle,OCP)。这个原则指出软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。访问者模式允许你在不改变对象结构中元素类的情况下定义一个新的操作,这样就可以在不修改现有代码的情况下增加新的功能。
常用实例:
访问者模式在开发中的一个常见应用是编译器。编译器通常需要对抽象语法树(AST)进行遍历,以执行诸如类型检查、代码生成等操作。使用访问者模式,可以将这些操作定义为访问者类,然后在遍历AST时调用相应的访问者方法。这样,当需要增加新的操作时,只需定义一个新的访问者类即可,而无需修改AST的结构。
类图:
![](https://img-blog.csdnimg.cn/10bd9270e3304a46847d570594e789a9.png)
代码:
#include "iostream"
#include "vector"
using namespace std;
class ConcreteElementA;
class ConcreteElementB;
class Visitor
{
public:
virtual void visitConcreteElementA(ConcreteElementA*elementA)=0;
virtual void visitConcreteElementB(ConcreteElementB*elementB)=0;
};
class Element
{
public:
virtual void accept(Visitor*visitor)=0;
};
class ConcreteElementA :public Element
{
public:
void accept(Visitor* visitor)
{
visitor->visitConcreteElementA(this);
}
void operationA()
{
cout<<"ConcreteElementA operation"<<endl;
}
};
class ConcreteElementB :public Element
{
public:
void accept(Visitor* visitor)
{
visitor->visitConcreteElementB(this);
}
void operationB()
{
cout<<"ConcreteElementB operation"<<endl;
}
};
class ConcreteVisitor1 :public Visitor
{
public:
void visitConcreteElementA(ConcreteElementA* elementA)
{
elementA->operationA();
}
void visitConcreteElementB(ConcreteElementB* elementB)
{
elementB->operationB();
}
};
class ConcreteVisitor2 :public Visitor
{
public:
void visitConcreteElementA(ConcreteElementA* elementA)
{
elementA->operationA();
}
void visitConcreteElementB(ConcreteElementB* elementB)
{
elementB->operationB();
}
};
class ConcreteVisitor3 :public Visitor
{
public:
void visitConcreteElementA(ConcreteElementA* elementA)
{
elementA->operationA();
//可在此处扩展
cout<<"sss"<<endl;
}
void visitConcreteElementB(ConcreteElementB* elementB)
{
elementB->operationB();
//可在此处扩展
cout << "sss" << endl;
}
};
class ObjectStructure
{
public:
void attach(Element* element)
{
elements.push_back(element);
}
void detach(Element* element)
{
for (vector<Element*>::iterator it=elements.begin();it!=elements.end();++it)
{
if (*it == element)
{
elements.erase(it);
break;
}
}
}
void accept(Visitor* visitor)
{
for (auto elment : elements)
{
elment->accept(visitor);
}
}
private:
vector<Element*>elements;
};
int main()
{
ObjectStructure objectStructure;
ConcreteElementA elementA;
ConcreteElementB elementB;
objectStructure.attach(&elementA);
objectStructure.attach(&elementB);
ConcreteVisitor1 visitor1;
ConcreteVisitor2 visitor2;
objectStructure.accept(&visitor1);
objectStructure.accept(&visitor2);
return 0;
}