访问者模式
介绍:
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
访问者模式是为了将数据结构与数据操作分离。
定义:
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
结构图:
代码:
Visitor类
为该对象结构中每一个ConcreteElement类声明一个Visit操作,用于具体访问者操作这些结构的数据。
class Visitor
{
public:
//声明对数据元素A类的访问操作
void VisitConcreteElementA(const ConcreteElementA &cConcreteElementA)=0;
//声明对数据元素B类的访问操作
void VisitConcreteElementB(const ConcreteElementB &cConcreteElementB)=0;
}
//ConcreteVisitor类
具体访问者,实现具体的访问操作
class ConcreteVisitor1 : Visitor
{
public:
//声明对数据元素A类的访问操作
void VisitConcreteElementA(const ConcreteElementA &cConcreteElementA)
{
//对数据元素A的访问和操作
...;
}
//声明对数据元素B类的访问操作
void VisitConcreteElementB(const ConcreteElementB &cConcreteElementB)
{
//对数据元素B的访问和操作
...;
}
}
class ConcreteVisitor2 : Visitor
{
public:
//声明对数据元素A类的访问操作
void VisitConcreteElementA(const ConcreteElementA &cConcreteElementA)
{
//对数据元素A的访问和操作
...;
}
//声明对数据元素B类的访问操作
void VisitConcreteElementB(const ConcreteElementB &cConcreteElementB)
{
//对数据元素B的访问和操作
...;
}
}
//Element类,定义一个Accept操作,以一个访问者为入参
class Element
{
public:
//传入具体访问者,调用接口实现访问者对数据元素的访问操作
void Accept(const Visitor &cVisitor)=0;
}
//具体数据元素类
class ConcreteElementA : Element
{
public:
//传入具体访问者,调用接口实现访问者对数据元素的访问操作
void Accept(const Visitor &cVisitor)
{
cVisitor.VisitConcreteElementA(this);
}
...;//其他相关方法
}
class ConcreteElementB : Element
{
public:
//传入具体访问者,调用接口实现访问者对数据元素的访问操作
void Accept(const Visitor &cVisitor)
{
cVisitor.VisitConcreteElementB(this);
}
...;//其他相关方法
}
//客户端
Element* pElementA = new ConcreteElementA();
Element* pElementB = new ConcreteElementB();
Visitor* pVisitor1 = new ConcreteVisitor1();
Visitor* pVisitor2 = new ConcreteVisitor2();
pElementA.Accept(pVisitor1);//实现pVisitor1对pElementA的访问操作
pElementB.Accept(pVisitor1);//实现pVisitor1对pElementB的访问操作
使用时机:
对象结构比较稳定,但经常需要在此对象结构上定义新的操作。
需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。
优点:
1、将数据结构和作用于结构之上的操作解耦合,使得操作集合可以相对自由的演化。
缺点:
使新加数据结构变得困难。