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

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

  Robert C. Martin提出了一种无环的访问者模式来改进原有的不足,通过改进后,循环依赖被打破了,也不要求被访问层次必须是
稳定的,即使是被访问者继承层次修改了,也不需要修改访问者层次,只需要扩展一下即可,而且访问者可以自由组合较之以前更

为灵活方便。但是也是有代价的,有一个向下的转换,性能会稍有损失,但相对于改进的好处来说,这点损失几乎可以忽略了。

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

///////////////访问者基类
template<typename T>
struct Visitor
{
virtual void Visit( T&) = ;
}; struct VistorToken
{
virtual ~VistorToken(){}
}; /////////////////被访问者基类
struct Base
{
virtual void Accept(VistorToken&) = ;
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,欢迎大家来交流技术。

无环的visitor模式的更多相关文章

  1. UVA_1025 a Spy in the Metro 有向无环图的动态规划问题

    应当认为,有向无环图上的动态规划问题是动态规划的基本模型之一,对于某个模型,如果可以转换为某一有向无环图的最长.最短路径问题,则可以套用动态规划若干方法解决. 原题参见刘汝佳紫薯267页. 在这个题目 ...

  2. Visitor模式,Decorator模式,Extension Object模式

    Modem结构 Visitor模式 对于被访问(Modem)层次结构中的每一个派生类,访问者(Visitor)层次中都有一个对应的方法. 从派生类到方法的90度旋转. 新增类似的Windows配置函数 ...

  3. [转帖]MerkleDAG全面解析 一文读懂什么是默克尔有向无环图

    MerkleDAG全面解析 一文读懂什么是默克尔有向无环图 2018-08-16 15:58区块链/技术 MerkleDAG作为IPFS的核心数据结构,它融合了Merkle Tree和DAG的优点,今 ...

  4. Behavioral模式之Visitor模式

    1.意图 表示一个作用于某对象结构中的各元素的操作.它使你能够在不改变各元素的类的前提下定义作用于这些元素的新操作. 2.别名 无 3.动机 考虑一个编译器.他将源程序表示为一个抽象语法树.该编译器须 ...

  5. 完成C++不能做到的事 - Visitor模式

    拿着刚磨好的热咖啡,我坐在了显示器前.“美好的一天又开始了”,我想. 昨晚做完了一个非常困难的任务并送给美国同事Review,因此今天只需要根据他们提出的意见适当修改代码并提交,一周的任务就完成了.剩 ...

  6. 有向无环图的应用—AOV网 和 拓扑排序

    有向无环图:无环的有向图,简称 DAG (Directed Acycline Graph) 图. 一个有向图的生成树是一个有向树,一个非连通有向图的若干强连通分量生成若干有向树,这些有向数形成生成森林 ...

  7. JavaScript + SVG实现Web前端WorkFlow工作流DAG有向无环图

    一.效果图展示及说明 (图一) (图二) 附注说明: 1. 图例都是DAG有向无环图的展现效果.两张图的区别为第二张图包含了多个分段关系.放置展示图片效果主要是为了说明该例子支持多段关系的展现(当前也 ...

  8. 湖南省第十二届大学生计算机程序设计竞赛 B 有向无环图 拓扑DP

    1804: 有向无环图 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 187  Solved: 80[Submit][Status][Web Board ...

  9. javascript实现有向无环图中任意两点最短路径的dijistra算法

    有向无环图 一个无环的有向图称做有向无环图(directed acycline praph).简称DAG 图.DAG 图是一类较有向树更一般的特殊有向图, dijistra算法 摘自 http://w ...

随机推荐

  1. 深入理解js——函数和对象的关系

    函数也是对象,但是函数却不像数组--数组是对象的一种,它是对象的一个子集.函数和数组之间不是单纯的包含与被包含的关系,它们之间有点像鸡生蛋蛋生鸡的逻辑. 来例子:function Fn(){ this ...

  2. Win7 64位系统 VS2010连接Oracle报错的问题

    1,异常现象: TNS无法识别 2,异常分析:VS2010启动调试的时候,出现异常.但是使用IIS作为服务器的时候,是不会出现异常,也就是可以正常访问到数据库,后来分析是由于VS自带服务器ASP.NE ...

  3. SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null' 解决办法

    当跑jndi项目时抛出:org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' fo ...

  4. Xml文件操作的其中一个使用方法:

    XmlNodeList students = doc.DocumentElement.ChildNodes;//Student节点集合 foreach (XmlNode stu in students ...

  5. oracle数据学习第二天

    今天主要加强了对oracle数据库的数据类型一些相关函数的学习  (一)char和varchar2  字符串函数 <1>concat(char1,char2)字符串连接函数,用于连接两个字 ...

  6. windowsAPI popup trace tip(toolTip)

    class UIHELPER_EXPORT ToolTipWindow : public chMessageHandler{ DECLARE_PROCESS_OBJECT(ToolTipWindow) ...

  7. SAP 如何查看用户登录信息

    1.首先进入事务代码 SM19  配置审计参数文件 2.选择客户端,用户名,并且勾选过滤激活之后点击细节配置,进入如下界面: 配置完成之后,点击保存. 3.并且可以进入SM20界面,选择要查看的客户端 ...

  8. LoadRunner录制不弹出IE浏览器,event=0

    系统环境:win7,安装了IE.360.firefox.搜狗高速浏览器: 起初刚装完loadrunner11的时候,选了IE进行录制,就是不能打开IE,算了,那就用loadrunner默认的设置,居然 ...

  9. hdu 5791 (DP) Two

    hdu 5791 Two Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  10. XE3随笔5:Format与转义字符

    unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For ...