ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

编程模式之访问者

2021-12-24 17:34:06  阅读:193  来源: 互联网

标签:Visitor 编程 模式 ReturnType virtual Visitee public 访问者


访问者模式,个人理解为是一个分类器,可以把抽象类型恢复到具体类型。面向对象的子类父类就是为了解决抽象、具体的问题。抽象的接口不好定义,免不了少定义了,又要改接口,而有些接口可能还不是很适用于每个具现类,这个时候是要定义抽象接口还是不需要呢,程序员又得费脑细胞了。访问者模式可以方便的将抽象类型落实到具体类型对象。也就是说,你给我一个箱子说装着一个动物,让我给准备食物,通过访问者模式就知道了它原来是一个狗狗,那就准备骨头吧。而且随时可以组织一个喂食访问者、或者一个防疫访问者,不用去修改动物这个类型的接口。这个模式也是实际使用最多的模式之一。

一般来说访问者模式要有一个Element抽象类,定义被访问者的基础方法Accept。一个访问者基类Visitor,定义了所有Element的具现类的访问接口。所以一般来说要求Eelement的具现类要稳定,否则,Visitor接口要反复修改就不太妙了。而且如果有些具体Visitor只处理一部分Element种类的情况也麻烦,还说上面的动物,如果一个具体的Visitor要看一个动物是否是鸡,如果是鸡就打预防针,否则不管。就这样的一个功能,还要处理其他各种动物的接口就不美了。

下面介绍本人实现的访问者模式,可以灵活组织,避免不少麻烦,经过多年的应用,基本没有修改过。

//所有Visitor的基类

//让所有的Visitor有一个统一的接口

class Base_Visitor

{

public:

    virtual ~Base_Visitor(){};

};

//对每个具体的Visitee进行访问的基类

template<class T,typename R>

class Visitor

{

public:

    virtual ~Visitor(){};

    typedef  R ReturnType;

public:

    //对Visitee对象的访问和扩展

    virtual  ReturnType  Visit(T&) = 0;

};

template<typename R = void>

class  Visitee

{

public:

    virtual ~Visitee(){};

    typedef  R  ReturnType;

public:

    //和宏DEFINE_Visitee配合把具体Visitee和visitor建立关联

    virtual  ReturnType  Accept(Base_Visitor& visitor) = 0;

protected:

    //静态函数,目的是为了visitor能访问具体的Visitee对象

    //也是和DEFINE_Visitee配合,对具体的Visitee对象T进行访问注册

    template<class T>

    static  ReturnType  AcceptImpl(T& visitee, Base_Visitor& guest)

    {

        Visitor<T, ReturnType>* p = dynamic_cast<Visitor<T, ReturnType>*>(&guest);

        //把具体的Visitee注册到对应的Visitor中

        //Visitor由BaseVisitor派生,并且以具体的Visitee类为模板参数

        if(NULL != p)

        {

            return p->Visit(visitee);

        }

        return ReturnType();

    }

};

#define DEFINE_VISITEE() \

    public:                \

    virtual ReturnType Accept(Base_Visitor& visitor) \

{ return AcceptImpl(*this, visitor); }  

应用示例:

class A : public Visitee<bool>

{

     DEFINE_VISITEE()

}

class B : public Visitee<bool>

{

    DEFINE_VISITEE()

}

Class C : public Visitee<bool>

{

    DEFINE_VISITEE()

}

class ABVisitor : public Base_Visitor,public Visitor<A,bool>,public Visitor<B,bool>

{

       virtual bool Visit(A& obj)

{

     //do somthing

     return true;

}

virtual bool Visit(B& obj)

{

   return true;

}

}

C cObj;

ABVisitor v;

bool b = cObj.Accept(v);//b == false;

B bObj;

b = bObj.Accept(v);//b == true;

如例:Visitor可以随时组织,可以对被访问者的一部分进行访问操作,也可以对全体进行访问操作。新写的代码不影响以前的代码,即使多了对象D,如果非逻辑需求,以前写的Visitor也可以不处理。

比如做一个图形系统:

圆、矩形、多边形、扇形、直线、折线都继承自Visitee。将一张图中的所有对象序列化,就可以用一个Visitor,将一张图所有对象写成XML格式文件可以用另一个Visitor,可以有一个Visitor给所有有面积的设置填充颜色。当鼠标选中一个图形对象的时候,可以用一个Visitor给这个选中对象分配对应的编辑对象来处理鼠标键盘事件。总之,需要针对不同对象处理什么事情的时候就可以写一个Visitor,很方便扩展。不用修改以前的代码,非常符合模式的基本原则。

访问者模式可以和消息树结合应用,减少消息树不必要的动态类型转换,也就是利用访问者模式,将消息具体到具体消息,再进行具体操作,读者可以先自行考虑,应该是水到渠成。笔者有时间再写吧。

标签:Visitor,编程,模式,ReturnType,virtual,Visitee,public,访问者
来源: https://blog.csdn.net/shtarliu/article/details/122132008

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有