1、意图
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作
2、适用性
在下列情况下使用Visitor模式:
1)一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2)需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一类中。当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
3)定义对象结构的类很少改变,当经常需要在此结构上定义新的操作。改变对象结构类需要重定义所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
3、C++实例
// Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <list>
#include <string>
using namespace std;
class Element;
class ElementA;
class ElementB;
class Visitor
{
public:
virtual void VisitElementA( ElementA *a ) = 0;
virtual void VisitElementB( ElementB *b ) = 0;
protected:
Visitor()
{
}
};
class Element
{
public:
virtual ~Element()
{
}
virtual void Accept( Visitor& v ) = 0;
protected:
Element()
{
}
};
class ElementA:public Element
{
public:
ElementA()
{
}
virtual void Accept( Visitor& v )
{
v.VisitElementA( this );
}
};
class ElementB:public Element
{
public:
ElementB()
{
}
virtual void Accept( Visitor& v )
{
v.VisitElementB( this );
}
};
class CompositeElement:public Element
{
public:
CompositeElement()
{
_children = new list<Element*>;
}
~CompositeElement()
{
if ( NULL != _children )
{
delete _children;
}
}
virtual void Accept( Visitor &v )
{
list<Element*> i( *_children );
list<Element*>::iterator iter = i.begin();
for ( ; iter != i.end(); iter++ )
{
Element *e = *iter;
e->Accept( v );
}
}
void PushElement( Element *e ) const
{
_children->push_back( e );
}
private:
list<Element*>* _children;
};
class ConcreteVisitorA:public Visitor
{
public:
ConcreteVisitorA()
{
}
public:
virtual void VisitElementA( ElementA *a )
{
cout<<" ConcreteVisitorA::VisitElementA "<<endl;
}
virtual void VisitElementB( ElementB *b )
{
cout<<" ConcreteVisitorA::VisitElementB "<<endl;
}
};
class ConcreteVisitorB:public Visitor
{
public:
ConcreteVisitorB()
{
}
public:
virtual void VisitElementA( ElementA *a )
{
cout<<" ConcreteVisitorB::VisitElementA "<<endl;
}
virtual void VisitElementB( ElementB *b )
{
cout<<" ConcreteVisitorB::VisitElementB "<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
ElementA *elementa = new ElementA;
ElementB *elementb = new ElementB;
CompositeElement compelement;
compelement.PushElement( elementa );
compelement.PushElement( elementb );
Visitor *visitora = new ConcreteVisitorA;
compelement.Accept( *visitora );
Visitor *visitorb = new ConcreteVisitorB;
compelement.Accept( *visitorb );
delete visitora;
delete visitorb;
delete elementa;
delete elementb;
return 0;
}