访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作,它使你可你在不改变各元素类的前提下定义作用于这些元素的新操作。
五个角色类:
- Visitor:为该对象结构中ConcreteElement的每一个类声明一个Visit操作。
- ConcreteVistor:具体访问者,实现每个由Visitor声明的操作。每个操作实现算法的一部分,而该算法片段是对应于结构中对象的类。
- ELement定义一个Accept操作,它以一个访问者为参数。
- ConcreteElement具体元素,实现Accept操作
- ObjectStructure能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素。
适用场合:
- 适用于数据结构相对稳定的系统,它把数据结构和作用于数据结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。
- 访问者模式的目的是要把处理从数据结构分离出来。很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。
其优点:
访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。
其缺点:
使增加新的数据结构变得困难。
模式实现:
class ConcreteElementA;
class ConcreteElementB;
class Visitor
{
public:
virtual void VisitConcreteElementA(ConcreteElementA *pElementA) = 0;
virtual void VisitConcreteElementB(ConcreteElementB *pElementB) = 0;
};
class ConcreteVisitor1 : public Visitor
{
public:
void VisitConcreteElementA(ConcreteElementA *pElementA);
void VisitConcreteElementB(ConcreteElementB *pElementB);
};
void ConcreteVisitor1::VisitConcreteElementA(ConcreteElementA *pElementA)
{
// 现在根据传进来的pElementA,可以对ConcreteElementA中的element进行操作
}
void ConcreteVisitor1::VisitConcreteElementB(ConcreteElementB *pElementB)
{
// 现在根据传进来的pElementB,可以对ConcreteElementB中的element进行操作
}
class ConcreteVisitor2 : public Visitor
{
public:
void VisitConcreteElementA(ConcreteElementA *pElementA);
void VisitConcreteElementB(ConcreteElementB *pElementB);
};
void ConcreteVisitor2::VisitConcreteElementA(ConcreteElementA *pElementA)
{
// ...
}
void ConcreteVisitor2::VisitConcreteElementB(ConcreteElementB *pElementB)
{
// ...
}
// Element object
class Element
{
public:
virtual void Accept(Visitor *pVisitor) = 0;
};
class ConcreteElementA : public Element
{
public:
void Accept(Visitor *pVisitor);
};
void ConcreteElementA::Accept(Visitor *pVisitor)
{
pVisitor->VisitConcreteElementA(this);
}
class ConcreteElementB : public Element
{
public:
void Accept(Visitor *pVisitor);
};
void ConcreteElementB::Accept(Visitor *pVisitor)
{
pVisitor->VisitConcreteElementB(this);
}
// ObjectStructure类,能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素
class ObjectStructure
{
public:
void Attach(Element *pElement);
void Detach(Element *pElement);
void Accept(Visitor *pVisitor);
private:
vector<Element *> elements;
};
void ObjectStructure::Attach(Element *pElement)
{
elements.push_back(pElement);
}
void ObjectStructure::Detach(Element *pElement)
{
vector<Element *>::iterator it = find(elements.begin(), elements.end(), pElement);
if (it != elements.end())
{
elements.erase(it);
}
}
void ObjectStructure::Accept(Visitor *pVisitor)
{
// 为每一个element设置visitor,进行对应的操作
for (vector<Element *>::const_iterator it = elements.begin(); it != elements.end(); ++it)
{
(*it)->Accept(pVisitor);
}
}
测试用例:
int main()
{
ObjectStructure *pObject = new ObjectStructure;
ConcreteElementA *pElementA = new ConcreteElementA;
ConcreteElementB *pElementB = new ConcreteElementB;
pObject->Attach(pElementA);
pObject->Attach(pElementB);
ConcreteVisitor1 *pVisitor1 = new ConcreteVisitor1;
ConcreteVisitor2 *pVisitor2 = new ConcreteVisitor2;
pObject->Accept(pVisitor1);
pObject->Accept(pVisitor2);
if (pVisitor2) delete pVisitor2;
if (pVisitor1) delete pVisitor1;
if (pElementB) delete pElementB;
if (pElementA) delete pElementA;
if (pObject) delete pObject;
return 0;
}