场景
根据Visitor模式的结构图和自己的理解.
如图:
图1
代码
class ObjectStruct
{
public:
Element* m_pElementA;
Element* m_pElementB;
// 你也可以使用一个数组, 列表等来存储里面的ObjectStruct中的元素.
// 因为这里使用的是父类Element的指针, 所以你在使用
// Visitor::VisitConcreteElementA和Visitor::VisitConcreteElementB传入的参数必须是正确的参数类型
};
//
class Visitor
{
public:
...
vritual void VisitConcreteElementA(ConcreteElementA* pConcreteElementA);
vritual void VisitConcreteElementB(ConcreteElementB* pConcreteElementB);
// 有objectStruct中多少个具体Element, 就需要多少个VisitConcreteElement函数.
};
//
class ConcreteVisitor1 : public Visitor
{
public:
...
vritual void VisitConcreteElementA(ConcreteElementA* pConcreteElementA);
vritual void VisitConcreteElementB(ConcreteElementB* pConcreteElementB);
// 有objectStruct中多少个具体Element, 就需要多少个VisitConcreteElement函数.
};
...
void ConcreteVisitor1::VisitConcreteElementA(ConcreteElementA* pConcreteElementA)
{
...
pConcreteElementA->OperationA();
...
}
void ConcreteVisitor1::VisitConcreteElementB(ConcreteElementB* pConcreteElementB)
{
...
...
pConcreteElementB->OperationB();
...
}
//
class ConcreteVisitor2 : public Visitor
{
public:
...
vritual void VisitConcreteElementA(ConcreteElementA* pConcreteElementA);
vritual void VisitConcreteElementB(ConcreteElementB* pConcreteElementB);
// 有objectStruct中多少个具体Element, 就需要多少个VisitConcreteElement函数.
};
...
void ConcreteVisitor2::VisitConcreteElementA(ConcreteElementA* pConcreteElementA)
{
pConcreteElementA->OperationA();
......
......
}
void ConcreteVisitor2::VisitConcreteElementB(ConcreteElementB* pConcreteElementB)
{
...
...
...
pConcreteElementB->OperationB();
}
//
class Element
{
public:
...
vritual void Accept(Visitor* pVisitor) = 0;
};
//
class ConcreteElementA : public Element
{
public:
...
vritual void Accept(Visitor* pVisitor) ;
void OperationA(); // 一些操作, 可以供其他类调用, 例如Visitor
};
// 这里是理解关键
void ConcreteElementA ::Accept(Visitor* pVisitor)
{
pVisitor->VisitConcreteElementA(this);
}
//
class ConcreteElementB : public Element
{
public:
...
vritual void Accept(Visitor* pVisitor);
void OperationB(); // 一些操作, 可以供其他类调用, 例如Visitor
};
// 这里是理解关键
void ConcreteElementB ::Accept(Visitor* pVisitor)
{
pVisitor->VisitConcreteElementB(this);
}
// Client 调用
// 1. 构建ObjectStruct对象(这里的构建过程应该与Visitor模式无关的, 根据自己需求来构建)
ObjectStruct* pObjectStruct = new ObjectStruct;
pObjectStruct->m_pElementA = new ConcreteElementA;
pObjectStruct->m_pElementB= new ConcreteElementB;
// 2. 使用访问者来操作
ConcreteVisitor1* pConcreteVisitor1 = new ConcreteVisitor1;
pObjectStruct->m_pElementA->Accept(pConcreteVisitor1 );
ConcreteVisitor2* pConcreteVisitor1 = new ConcreteVisitor2;
pObjectStruct->m_pElementA->Accept(pConcreteVisitor2 );
pObjectStruct->m_pElementB->Accept(pConcreteVisitor1 );
// 看协作图
我的理解
1. ObjectStruct与具体Visitor是解耦的, ObjectStruct可以不需要知道具体的Visitor, 它通过Element::Accept(Visitor* pVisitor)来操作具体Element.
2. 假设不使用Visitor模式, 如果增加Element的操作, 则你需要修改对应的具体Element, 这样修改的话, ObjectStruct也对应的被间接修改了. 而如果使用Visitor模式, 则只需要增加一个具体Visitor类和在调用的地方修改即可.
3. 增加具体Visitor简答方便, 但ObjectStruct增加一个Element, 则Visitor层次需要改变Visitor的接口, 例如增加一个ElementC, Visitor类需要增加操作ElementC的接口, 抽象父类增加了接口, 它的所有子类也要增加. (笛卡尔积)
4. Visitor模式的这种增加一个具体Element时需要对Visitor的接口改变的问题与Abstract Factory模式有点相似, 就是在Abstract Factory模式中, 如果需要增加一个产品AbstractProductC, 你需要在AbstractFactory类上增加一个创建新AbstractProductC的接口, 从而所有的具体Factory也要实现这个接口.