Visitor模式

来源:互联网 发布:遗传算法的具体应用 编辑:程序博客网 时间:2024/06/10 07:40

作用:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的操作。

解析:Vistor模式把对结点的访问封装成一个抽象基类,通过派生出不同的类生成新的访问方式。在实现的时候,在visitor抽象基类中声明了对所有不同结点进行访问的函数,如VisitConcreteElementA函数等,这样也造成了Visitor模式的一个缺陷:新加入一个结点的时候都要添加visitor中的对其进行访问的接口函数,这样使得所有的Visitor及其派生类都要重新编译了,也就是说Visitor模式一个缺点就是添加新的结点十分困难。另外,还需要指出的是Visitor模式采用了所谓的“双重分派”的技术,拿下图作为例子,要对某一个结点进行访问,首先需要产生一个Element的派生类对象,其次要传入一个Visitor类派生类对象来调用对应的Accept函数,也就是说,到底对哪种Element采用哪种Visitor访问,需要两次动态绑定才可以确定下来,具体的实现可参考实现代码中的VisitorMain.cpp部分是如何调用这些类的。

大话设计模式:访问者模式适用于数据结构相对稳定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。

访问者模式的目的是要把处理从数据结构分享出来。有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。

访问者模式的优点:增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。

访问者模式的缺点:使增加新的数据结构变得困难。

 

 

 

代码实现:

**************************************

Visitor.h        janvyking999

**************************************

class Visitor;

class Element {

public:

    virtual ~Element() {}

    virtual void accept(Visitor* rVisitor) = 0; //用来获得状态对象的

protected:

    Element() {}

};

 

class ConcreteElementA: public Element {

public:

    virtual ~ConcreteElementA() {}

    virtual void accept(Visitor* rVisitor);

};

 

class ConcreteElementB: public Element {

public:

    virtual ~ConcreteElementB() {}

    virtual void accept(Visitor* rVisitor);

};

 

class Visitor {

public:

    virtual ~Visitor() {}

    virtual void VisitConcreteElementA(ConcreteElementA* pConcreteElementA) = 0;

    virtual void VisitConcreteElementB(ConcreteElementB* pConcreteElementB) = 0;

protected:

    Visitor() {}

};

 

class ConcreteVisitorA: public Visitor {

public:

    virtual ~ConcreteVisitorA() {}

    virtual void VisitConcreteElementA(ConcreteElementA* pConcreteElementA);

    virtual void VisitConcreteElementB(ConcreteElementB* pConcreteElementB);

 

};

 

class ConcreteVisitorB: public Visitor {

public:

    virtual ~ConcreteVisitorB() {}

    virtual void VisitConcreteElementA(ConcreteElementA* pConcreteElementA);

    virtual void VisitConcreteElementB(ConcreteElementB* pConcreteElementB);

 

};

**************************************

Visitor.cpp        janvyking999

**************************************

#include <iostream>

#include "Visitor.h"

using namespace std;

//首先在客户程序中将具体Visitor(状态)作为参数传递给ConcreteElementA(男人)类完成了一次分派,

//然后CEA类调用作为参数的CV类中的方法VCE,同时将自己(this)作为参数传递进去,这便完成第二次分派。

void ConcreteElementA::accept(Visitor *rVisitor) {

    rVisitor->VisitConcreteElementA(this);

}

 

void ConcreteElementB::accept(Visitor *rVisitor) {

    rVisitor->VisitConcreteElementB(this);

}

 

void ConcreteVisitorA::VisitConcreteElementA(ConcreteElementA *pConcreteElementA) {

    cout<<"VisitConcreteElementA by ConcreteVisitorA"<<endl;

}

 

void ConcreteVisitorA::VisitConcreteElementB(ConcreteElementB *pConcreteElementB) {

    cout<<"VisitConcreteElementB by ConcreteVisitorB"<<endl;

}

 

void ConcreteVisitorB::VisitConcreteElementA(ConcreteElementA *pConcreteElementA) {

    cout<<"VisitConcreteElementA by ConcreteVisitorB"<<endl;

}

 

void ConcreteVisitorB::VisitConcreteElementB(ConcreteElementB *pConcreteElementB) {

    cout<<"VisitConcreteElementB by ConcreteVisitorB"<<endl;

}

**************************************

VisitorMain.cpp        janvyking999

**************************************

#include "Visitor.h"

 

int main() {

    Visitor* pVisitorA = new ConcreteVisitorA();

    Element* pElementA = new ConcreteElementA();

 

    pElementA->accept(pVisitorA);

 

    delete pElementA;

    delete pVisitorA;

    return 0;

}

程序输出:

VisitConcreteElementA by ConcreteVisitorA

原创粉丝点击