访问者模式

访问者模式是一种分离对象数据结构与行为的方法,通过这种分离,可以为一个已存在的类或类群(即被访问者)增加新的操作(即访问者)而无需为它们作任何修改。访问者模式属于行为型模式。

为什么要使用访问者模式?
    如何扩展一个现有的类层次结构来实现新行为?一般的方法是给类添加新的方法。但是万一新行为和现有对象模型不兼容怎么办?还有,类层次结构设计人员可能无法预知以后开发过程中将会需要哪些功能。以及,如果已有的类层次结构不允许修改代码,怎么能扩展行为呢? 
    答案是在类层次结构设计中使用访问者模式。

 访问者模式涉及的角色:

1)访问者(Visitor)
    访问者抽象接口,通过visit(Element)方法访问Element(数据结构),完成对Element的操作行为。
2)具体访问者(ConcreteVisitor)
    访问者的具体实现类。
3)元素(Element),也就是被访问者
    通过accept(Visitor)方法接受Visitor的访问。
4)具体元素(ConcreteElement)
    元素的具体实现类。
5)对象结构(ObjectStructure)
    拥有一组元素的组合对象。ObjectStructure本身也可以作为被访问者。

我在这里写了一个访问者模式的应用,作为多灾多难的四川人民在地震后感谢全国人民的鼎力相援。

假设这里Visitor是捐助者,Element是灾区人民,ObejectSturcutre是政府组织救灾物资的发放假设各灾区收到的物资一样,那么访问者模式在这里就是有各种各样的捐助者捐助不同的东西到灾区,政府将这些东西均等的发放到灾区,最后灾区人民感谢捐助者。

#include<iostream>
#include<string>
#include<list>
using namespace std;
class Element;//灾区基类
class Visitor{//捐助者基类
    public:
        virtual void visit(Element*)=0;//捐助方法
        Visitor(int x=0):num(x){}
    public:
        int num;//捐助数量
};
class Element{
    public:
        virtual void accept(Visitor*)=0;//接受捐助方法
        Element(string s="四川"):name(s){}
    public:
        string name;//灾区名字
};
class ConcreteElement:public Element{
    public:
        void accept(Visitor* v){
            v->visit(this);//调用不同捐助者特有的捐助方法
        }
        ConcreteElement(string s="四川"){name=s;}
};
class Visitor_money:public Visitor{
    public:
        Visitor_money(int m=100){num=m;}
        void visit(Element* e){//钱财捐助者的捐助方法
            cout<<e->name<<"人民感谢您捐助钱财"<<num<<"元"<<endl;
        }
};
class Visitor_book:public Visitor{
    public:
        Visitor_book(int b=10){num=b;}
        void visit(Element* e){//捐助书籍者的捐助方法
            cout<<e->name<<"人民感谢您捐助书籍"<<num<<"册"<<endl;
        }
};
class ObjectStructure{//救灾物资统筹者,这里假设是政府
    private:
        list<ConcreteElement*> vec;//灾区队列
    public:
        void attach(ConcreteElement* x){
            vec.push_back(x);//添加灾区
        }
        void detach(ConcreteElement* x){
            vec.remove(x);//移除灾区
        }
        void accept(Visitor* v){
            for(list<ConcreteElement*>::iterator it=vec.begin();it!=vec.end();it++){
                (*it)->accept(v);//政府统筹下每个灾区都接受捐助者v相同数量的物资
            }
        }
};
int main(){
    ObjectStructure goverment;
    goverment.attach(new ConcreteElement("汶川"));
    goverment.attach(new ConcreteElement("雅安"));
    Visitor_money* v_m=new Visitor_money(1000000);
    Visitor_book* v_b=new Visitor_book(100000);
    goverment.accept(v_m);
    goverment.accept(v_b);
    return 0;
}
输出:


访问者模式的优点

  • 符合单一职责原则:凡是适用访问者模式的场景中,元素类中需要封装在访问者中的操作必定是与元素类本身关系不大且是易变的操作,使用访问者模式一方面符合单一职责原则,另一方面,因为被封装的操作通常来说都是易变的,所以当发生变化时,就可以在不改变元素类本身的前提下,实现对变化部分的扩展。
  • 扩展性良好:元素类可以通过接受不同的访问者来实现对不同操作的扩展。

 访问者模式的适用场景

       假如一个对象中存在着一些与本对象不相干(或者关系较弱)的操作,为了避免这些操作污染这个对象,则可以使用访问者模式来把这些操作封装到访问者中去。

       假如一组对象中,存在着相似的操作,为了避免出现大量重复的代码,也可以将这些重复的操作封装到访问者中去。

       但是,访问者模式并不是那么完美,它也有着致命的缺陷:增加新的元素类比较困难。通过访问者模式的代码可以看到,在访问者类中,每一个元素类都有它对应的处理方法,也就是说,每增加一个元素类都需要修改访问者类(也包括访问者类的子类或者实现类),修改起来相当麻烦。也就是说,在元素类数目不确定的情况下,应该慎用访问者模式。所以,访问者模式比较适用于对已有功能的重构,比如说,一个项目的基本功能已经确定下来,元素类的数据已经基本确定下来不会变了,会变的只是这些元素内的相关操作,这时候,我们可以使用访问者模式对原有的代码进行重构一遍,这样一来,就可以在不修改各个元素类的情况下,对原有功能进行修改。



Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值