zoukankan      html  css  js  c++  java
  • 无环的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(VistorToken&) = 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,欢迎大家来交流技术。

  • 相关阅读:
    leetcode 141 环形链表
    [转载]Tensorflow中reduction_indices 的用法
    SIFT特征原理与理解
    numpy切片和布尔型索引
    IPython的使用
    [文献阅读]基于卷积神经网络的高光谱图像深度特征提取与分类
    验证码校验
    防止表单重复提交
    MyBatis 一对一,一对多,多对多
    MySQL基础内容
  • 原文地址:https://www.cnblogs.com/qicosmos/p/3357178.html
Copyright © 2011-2022 走看看