声明:本博文篇幅短,适合review。
一、概念
访问者模式就是表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
二、模式结构图
class Visitor
{
public:
virtual ~Visitor();
virtual void VisitConcreteElementA(Element* elm) = 0;
virtual void VisitConcreteElementB(Element* elm) = 0;
};
class ConcreteVisitorA : public Visitor {
public:
ConcreteVisitorA();
~ConcreteVisitorA();
void visitConcreteElementA(Element* elm){
cout<<"ConcreteVisitorA Visit A"<<endl;
}
void visitConcreteElementB(Element* elm){
cout<<"ConcreteVisitorA Visit B"<<endl;
}
};
class ConcreteVisitorB : public Visitor {
public:
ConcreteVisitorB();
~ConcreteVisitorB();
void visitConcreteElementA(Element* elm){
cout<<"ConcreteVisitorB Visit A"<<endl;
}
void visitConcreteElementB(Element* elm){
cout<<"ConcreteVisitorB Visit B"<<endl;
}
};
class Element
{
public:
virtual ~Element();
virtual void accept(Visitor* vis) = 0;
};
class ConcreteElementA : public Element {
public:
ConcreteElementA();
~ConcreteElementA();
void accept(Visitor* vis){
vis->visitConcreteElementA(this);
}
};
class ConcreteElementB : public Element {
public:
ConcreteElementB();
~ConcreteElementB();
void accept(Visitor* vis){
vis->visitConcreteElementB(this);
}
};
class ObjectStructure{
public:
void attach(Element * e){
mVec.push_back(e);
}
void detach(Element * e){
mVec.remove(e);
}
void accept(Visitor * v){
for (list<Element *>::iterator it = mVec.begin(); it != mVec.end(); it++){
(*it)->accept(v);
}
}
private:
list<Element *> mVec;
};
void main(){
ObjectStructure * ob = new ObjectStructure();
ob->attach(new ConcreteElementA());
ob->attach(new ConcreteElementB());
Visitor * visA = new ConcreteVisitorA();
Visitor * visB = new ConcreteVisitorB();
ob->accept(visA);
ob->accept(visB);
}
三、例子
class Business
{
public:
virtual ~Business();
virtual void doBySpcl(SellWindow* sw) = 0;
virtual void doByNml(SellWindow* sw) = 0;
};
class Buy : public Business {
public:
void doBySpcl(SellWindow* sw){
cout<<"Buy Special ticket "<<endl;
}
void doByNml(SellWindow* sw){
cout<<"Buy Normal ticket"<<endl;
}
};
class Change : public Business {
public:
void doBySpcl(SellWindow* sw){
cout<<"Change Special ticket"<<endl;
}
void doByNml(SellWindow* sw){
cout<<"Change Normal ticket"<<endl;
}
};
class SellWindow
{
public:
virtual ~SellWindow();
virtual void doBusiness(Business* bs) = 0;
};
class SpecialWindow : public SellWindow {
public:
void doBusiness(Business* bs){
bs->doBySpcl(this);
}
};
class NormalWindow : public SellWindow {
public:
void doBusiness(Business* bs){
bs->doByNml(this);
}
};
class SellHall{
public:
void attach(SellWindow * sw){
mVec.push_back(sw);
}
void detach(SellWindow * sw){
mVec.remove(sw);
}
void doBusiness(Business * bs){
for (list<SellWindow *>::iterator it = mVec.begin(); it != mVec.end(); it++){
(*it)->doBusiness(bs);
}
}
private:
list<SellWindow *> mVec;
};
void main(){
SellHall * sh = new SellHall();
sh->attach(new SpecialWindow());
sh->attach(new NormalWindow());
Buy * by = new Buy();
Change * cg = new Change();
sh->doBusiness(by);
sh->doBusiness(cg);
}
四、优缺点
1、优点
a、增加新的Visitor变得很容易,满足开闭原则。
b、访问者模式将有关的行为集中到一个Visitor对象中,而不是分散到一个个的Element中。
c、访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模式可以做到这一点。
2、缺点
a、不方便增加新的Element。
b、Visitor的访问暴露了Element的操作和状态,破坏了封装。