Visitor 模式也叫访问者模式,是行为模式之一,它分离对象的数据和行为,使用 Visitor模式,可以不修改已有类的情况下,增加新的操作角色和职责。
访问者模式适用于:
把数据结构 和 作用于数据结构上的操作 进行解耦合;适用于数据结构比较稳定的场合
访问者模式总结:
访问者模式优点是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。那访问者模式的缺点是是增加新的数据结构变得困难了。
访问者模式有如下的优点:
1,访问者模式使得增加新的操作变得很容易。如果一些操作依赖于一个复杂的结构对象的
话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增
加一个新的访问者类,因此,变得很容易。
2,访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
3,访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代只能
访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模
式可以做到这一点。
4,积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程
中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系统维
护的优点。
访问者模式有如下的缺点:
1,增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增加
一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。
2,破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一
个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问
就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存
储在节点对象中,这也是破坏封装的。
class ParkElement;
class Visitor {
public:
virtual void visit(ParkElement* park) = 0;
};
class ParkElement //每一个
{
public:
virtual void accept(Visitor* v) = 0;
void setElementName(string name)
{
m_name = name;
}
string getElementName() {
return m_name;
}
private:
string m_name;
};
class ParkA : public ParkElement
{
public:
virtual void accept(Visitor* v)
{
v->visit(this);
}
};
class ParkB : public ParkElement
{
public:
virtual void accept(Visitor* v)
{
v->visit(this);
}
};
class Park : public ParkElement
{
public:
Park()
{
m_list.clear();
}
void addParkElement(ParkElement* e)
{
m_list.push_back(e);
}
public:
void accept(Visitor* v)
{
for (list<ParkElement*>::iterator it = m_list.begin(); it != m_list.end(); it++)
{
(*it)->accept(v);
}
}
private:
list<ParkElement*> m_list;
};
class VisitorA : public Visitor
{
public:
virtual void visit(ParkElement* park)
{
cout << "Visitor A 访问 "<<park->getElementName() << endl;
}
};
class VisitorB : public Visitor
{
public:
virtual void visit(ParkElement* park)
{
cout << "Visitor B 访问 " << park->getElementName() << endl;
}
};
class VisitorManager : public Visitor
{
public:
virtual void visit(ParkElement* park)
{
cout << "VisitorManager 访问 "<< park->getElementName() << endl;
}
};
int main() {
VisitorA* visitorA = new VisitorA;
VisitorB* visitorB = new VisitorB;
ParkA* partA = new ParkA;
partA->setElementName("partA area");
ParkB* partB = new ParkB;
partB->setElementName("partB area");
//公园接受访问者 a 访问
/*partA->accept(visitorA);
partB->accept(visitorB);*/
VisitorManager* visitorManager = new VisitorManager;
Park* park = new Park;
park->addParkElement(partA);
park->addParkElement(partB);
park->accept(visitorManager);
delete partB;
delete partA;
delete visitorB;
delete visitorA;
system("pause");
return 0;
}