【设计模式】访问者

Visitor模式,顾名思义,就是有客人要来拜访,当然客人不一定是谁,我们家也不一定就我一个人。所以是一个N:M的一个关系。

但是我们家里的人一般都是比较固定的。就我跟我老婆,孩子,偶尔爸妈过来住一住。而来访者,可能是随便谁谁。他来我们家拜访,我肯定是要接待的。

一般至少得开个门吧,然后我们还会开放一些空间给她参观,比如客厅,每个人都是可以参观的。而对于每个家庭成员,visitor可能要有不同的方式打交道,不同的visitor跟我们家每个成员打交道方式可能都不太一样。比如我叔叔辈的可能跟我爸妈聊天会更多。如果是我同学,肯定就跟我聊得更多。


好了,到现在为止,出现了两个角色。Visitor和我们家成员。当然我们家成员可以共享一个客厅,但是每个人都有一些私人物品。这个就不继续扩展了。

一般我们家成员组成了一个家庭(Composit)。

抽象一下,访问者我们叫Visitor,家庭成员叫Element。家庭就是一个Composit。对应着访问者模式类图看看,应该都能对应上了吧?


简单写了个demo:

#include "Element.h"
class ElementA;
class ElementB;
class Element;
class Visitor{
public:    
    Visitor(){}
    ~Visitor(){}
    virtual void Visit(ElementA * ea);
    virtual void Visit(ElementB * eb);
    virtual void Visit(Element * e);
};
#include "Visitor.h"
void Visitor::Visit(ElementA * ea){
    cout<<"visit ElementA:"<<ea->GetName()<<":"<<ea->GetValue()<<endl;
    ea->SetValue(200);
    cout<<"after visit ElementA:"<<ea->GetName()<<":"<<ea->GetValue()<<endl;
}


void Visitor::Visit(ElementB * eb){
    cout<<"visit ElementB:"<<eb->GetName()<<":"<<eb->GetValue()<<endl;
    eb->SetValue(100);
    cout<<"after Visit ElementB:"<<eb->GetName()<<":"<<eb->GetValue()<<endl;
}


void Visitor::Visit(Element * e){
    cout<<"Visit Element Father:"<<e->GetName()<<":"<<e->GetValue()<<endl;
    e->SetValue(10);
    cout<<"after visit Element:"<<e->GetName()<<":"<<e->GetValue()<<endl;
}
#include <iostream>
#include "Visitor.h"
using namespace std;


class Visitor;
class Element{
public:
    Element(){}
    ~Element(){}
    virtual void Accept(Visitor * visitor);
    
    string & GetName(){
        return name;
    }
    void SetName(string n){
        name = n;
    }


    int & GetValue(){
        return value;
    }
    void SetValue(int i){
        value = i;
    }
    
protected:
    string name;
    int value;


};


class ElementA :public Element{
public:
    ElementA(){
        name = "ElementA";
        value = 10;
    }


    virtual void Accept(Visitor * visitor);
};


class ElementB : public Element{
public:
    ElementB(){
        name = "ElementB";
        value = 20;
    }
    ~ElementB(){}
    virtual void Accept(Visitor * visitor);
};
#include "Element.h"


void Element::Accept(Visitor * visitor){
    cout<<"do some job in Element Father"<<endl;
    visitor->Visit(this);
}


void ElementA::Accept(Visitor * visitor){
    cout<<"do some job in ElementA"<<endl;
    visitor->Visit(this);
}


void ElementB::Accept(Visitor * visitor){
    cout<<"do some job in ElementB"<<endl;
    visitor->Visit(this);
}
#include <iostream>
#include <list>
#include "Visitor.h"
#include "Element.h"
using namespace std;


int main(){
    //就不搞composit了,直接放到main里测试
    list<Element *> elem_list;
    ElementA *ea1 = new ElementA();
    elem_list.push_back(ea1);
    ElementA *ea2 = new ElementA();
    elem_list.push_back(ea2);


    ElementB *eb1 = new ElementB();
    elem_list.push_back(eb1);


    Visitor * v = new Visitor();


    list<Element *>::iterator iter = elem_list.begin();
    for (; iter != elem_list.end(); iter++){
        (*iter)->Accept(v);
    }
    
    return 0;
}

该模式中假设Element是比较稳定的,而Visitor是经常变的部分。如果Element变化比较频繁,那么Visitor修改成本会比较大。

可以在Visitor父类中增加一些默认操作。Element父类也有一些默认的Accept动作。

Visitor访问对象一般都是一个相似的集合/组合,但是对此没有严格要求。Element完全可以不同(不同父类),只需要Element有Accept方法,Visitor中增加对应的处理函数即可。这使得Visitor使用比较灵活。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值