zoukankan      html  css  js  c++  java
  • 无环的visitor模式

    无环的visitor模式

    无环的访问者模式,是来改进原有访问者模式的不足之处的,是Robert C. Martin首次提出的。我们知道访问者模式的优点是为被访问继承体系动态添加行为,而无须改变继承体系。但是GOF访问者模式的缺点是形成了一个循环依赖,强烈的耦合了两个继承体系,使得我们修改任何一方都会对另一方造成影响,所以GOF提出,被访问者的继承体系必须是稳定的,否则,一旦被访问的继承体系修改了,两边都要改。

    GOF访问者模式的UML类图。从图中可以看到循环依赖,一旦被访者体系发生变化,则访问者体系就要修改,这是难以接受的。

      Robert C. Martin提出了一种无环的访问者模式来改进原有的不足,通过改进后,循环依赖被打破了,也不要求被访问层次必须是 
    稳定的,即使是被访问者继承层次修改了,也不需要修改访问者层次,只需要扩展一下即可,而且访问者可以自由组合较之以前更 
    为灵活方便。但是也是有代价的,有一个向下的转换,性能会稍有损失,但相对于改进的好处来说,这点损失几乎可以忽略了。

      从上图我们可以看到,循环依赖被打破了,访问者基类不再依赖于被访问者的具体类型了,只是依赖于一个空的访问者基类,因此它是稳定的。通过多重继承,我们可以自由的组合访问者,比以前将访问函数放到一个类中更灵活。下面看看c++中具体的实现吧。

    复制代码
    ///////////////访问者基类
    template<typename T>
    struct Visitor
    {
        virtual void Visit( T&) = 0;
    };
    
    struct VistorToken
    {
        virtual ~VistorToken(){}
    };
    
    /////////////////被访问者基类
    struct Base
    {
        virtual void Accept(VisitorToken&) = 0;
        virtual ~Base(){}
    };
    
    /////////////////具体的被访问者
    struct AV;
    typedef Visitor<AV> AVVisitor;
    
    struct BV;
    typedef Visitor<BV> BVVisitor;
    
    struct AV : public Base
    {
        double val;
        void Accept(VistorToken& v)
        {
            if (AVVisitor* ev = dynamic_cast<AVVisitor*>(&v))
                ev->Visit(*this);
        }
    };
    
    struct BV : public Base
    {
        double val;
        void Accept(VistorToken& v)
        {
            if (BVVisitor* ev = dynamic_cast<BVVisitor*>(&v))
                ev->Visit(*this);
        }
    };
    
    ////////////////////////具体的自定义访问者
    struct CustomerVisitor : public VistorToken, public AVVisitor, public BVVisitor
    {
        void Visit(AV& a)
        {
            std::cout << "from AV: " << a.val << std::endl;
        }
        void Visit(BV& b)
        {
            std::cout << "from BV: " << b.val << std::endl;
        }
    };
    复制代码

    测试程序:

    复制代码
    void OtherVisitor()
    {
        AV a; a.val = 10.1;
        BV b; b.val = 9.2;
        CustomerVisitor v;
        Base* b1 = &a;
        Base* b2 = &b;
        b1->Accept(v);
        b2->Accept(v);
    }
    复制代码

      不知道无环的访问者模式我讲清楚没有,可能有点难理解,没关系,自己动手实践一下,再回过头来看介绍也许就明白了怎么回事了。

      c++11 boost技术交流群:296561497,欢迎大家来交流技术。

     
     
    分类: C++ 设计模式
  • 相关阅读:
    vim的modeline
    python的read() 、readline()、readlines()、xreadlines()
    hashset
    java泛型
    eclipse常用快捷键
    互联网计费模式
    cocos2d::CCFileUtils::sharedFileUtils()->getFileData(szFile, "r", &bufferSize) 不同平台返回值不一样
    CSS为英文和中文字体分别设置不同的字体
    fatal error C1010: 在查找预编译头时遇到意外的文件结尾
    JavaScript权威指南第03章 类型、值和变量(1)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3358302.html
Copyright © 2011-2022 走看看