我们先从字面上去理解它吧,直观地说,它指的是两次dispatch。这里的dispatch指的是什么呢?举个例子:

   class Event   {public:virtual void PrintName()           {                cout<<"我是通用事件"<<endl;                      }   }

class KeyEvent:public Event   {public:virtual void PrintName()           {                cout<<"我是按键事件"<<endl;                      }   }

class ClickEvent:public Event   {public:virtual void PrintName()           {                cout<<"我是单击事件"<<endl;                      }   }

多态性是动态的,被调用的方法由对象的真正类型确定,这个过程就被称之为dispatch。例如在C++中,每个对象都有一个虚函数表,当用基类的类型引用子类对象时,虚函数指针指向的是子类的虚函数表,调用的虚函数都是子类中的版本,所以下面代码输出的是:“我是按键事件”,这就算是一次dispatch的过程,即根据对象类型来动态确定调用哪个函数的过程。

   Event* pEvent = new KeyEvent();   pEvent->PrintName();

什么时候会用到两次dispatch呢? 继续往下看:

   class EventRecorder   {public:virtual void RecordEvent(Event* event)           {               cout<<"使用EventRecorder记录通用事件"<< endl;                      }

virtual void RecordEvent(KeyEvent* event)           {               cout<<"使用EventRecorder记录按键事件"<< endl;                      }

virtual void RecordEvent(ClickEvent* event)           {               cout<<"使用EventRecorder记录单击事件"<< endl;                      }   }

class AdvanceEventRecorder:public EventRecorder   {public:virtual void RecordEvent(Event* event)           {               cout<<"使用高级EventRecorder记录通用事件"<< endl;                      }

virtual void RecordEvent(KeyEvent* event)           {               cout<<"使用高级EventRecorder记录按键事件"<< endl;                      }

virtual void RecordEvent(ClickEvent* event)           {               cout<<"使用高级EventRecorder记录单击事件"<< endl;                      }   }

这两个类中分别包含三个重载函数,多态是动态的,而函数重载则是静态的,它在编译时期就确定下来了,所以,下面代码片段的运行结果并不是我们所期望的:

   EventRecorder* pRecorder = new AdvanceEventRecorder();   Event* pEvent = new KeyEvent();   pRecorder->RecordEvent(pEvent);

输出内容为:使用高级EventRecorder记录通用事件

实际上,在这个场景中,我们期望调用的是:AdvanceEventRecorder::RecordEvent(KeyEvent* event)

下面我们使用Double Dispatch设计模式来达到上面的代码片段的目的,在所有Event对象中增加下面的函数:

   virtual void RecordEvent(EventRecorder* recorder)   {      recorder->RecordEvent(this);   }

下面的代码片段将输出:使用高级EventRecorder记录按键事件

   EventRecorder* pRecorder = new AdvanceEventRecorder();   Event* pEvent = new KeyEvent();   pEvent->RecordEvent(pRecorder);

可以看出,第一次dispatch正确地找到了KeyEvent的RecordEvent(EventRecorder* recorder),第二次dispatch找到了AdvanceEventRecorder的RecordEvent(KeyEvent* event)。
   Visitor模式就是对Double Dispatch的应用,另外,在碰撞检测算法中也会经常用到。

转载于:https://www.cnblogs.com/west-link/archive/2011/07/26/2116887.html

GoF著作中未提到的设计模式(4):Double Dispatch相关推荐

  1. Java开发中的23种设计模式详解(转)

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  2. 如何丢弃Git中未进行的变更?

    如何丢弃工作副本中未包含在索引中的更改? #1楼 这会签出当前目录的当前索引,从而丢弃文件从当前目录向下的所有更改. git checkout . 或此操作从索引中检出所有文件,覆盖工作树文件. gi ...

  3. 【java】java开发中的23种设计模式详解

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  4. [Google Guava] 2.3-强大的集合工具类:java.util.Collections中未包含的集合工具

    原文链接 译文链接 译者:沈义扬,校对:丁一 尚未完成: Queues, Tables工具类 任何对JDK集合框架有经验的程序员都熟悉和喜欢java.util.Collections包含的工具方法.G ...

  5. Java中的中介器设计模式-示例教程

    中介者模式是行为设计模式之一 ,因此它处理对象的行为. 中介器设计模式用于在系统中不同对象之间提供集中式通信介质. 根据GoF,中介者模式意图是: 通过封装不同对象集相互交互和通信的方式,允许松散耦合 ...

  6. Java开发中的23种设计模式详解

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...

  7. 【设计模式】谈谈我们工作中的23个设计模式

    ID 标题 地址 1 设计模式面试题(总结最全面的面试题) https://writer.blog.csdn.net/article/details/127910080 2 Java基础知识面试题(总 ...

  8. java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...

    23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...

  9. 实战!工作中常用到哪些设计模式

    前言 平时我们写代码呢,多数情况都是流水线式写代码,基本就可以实现业务逻辑了.如何在写代码中找到乐趣呢,我觉得,最好的方式就是:使用设计模式优化自己的业务代码.今天跟大家聊聊日常工作中,我都使用过哪些 ...

最新文章

  1. ethereumjs/ethereumjs-util
  2. SAP系统中设备管理模块的主要增强出口
  3. 在Visual Studio中使用用例图描述系统与参与者间的关系
  4. Test live writer
  5. ASP.NET 构建高性能网站 架构设计
  6. 第5课 开心的金明《聪明人的游戏:信息学探秘.提高篇》
  7. MYSQL 表 部分数据导出、导入
  8. 异常的分类 java 1615309080
  9. Linux下 sshd服务不能启动
  10. java 内部类序列化_Gson如何序列化内部类
  11. 程序设计 关键字解释
  12. java newtonsoft.json_Newtonsoft.Json 的序列化与反序列化
  13. mysql 高可用架构 proxysql 之一 yum安装
  14. Image Upload based on jQuery
  15. h5页面编写注意事项,自己遇到的小问题。
  16. Java多组输入实现 C++多组输入实现
  17. 离散小波变换wavedec matlab,MATLAB小波变换指令及其功能介绍(超级有用)
  18. 郭盛华:互联网安全可能是下一个热门投资主题
  19. 关于获取日周月的时间处理与日期联动处理
  20. 入门级练习题(1-15)

热门文章

  1. Web 2.0与云计算
  2. php获得每个月第一天的时间,PHP获取指定日期所在月的第一天和最后一天几个例子...
  3. 实验楼python挑战答案_python基础知识
  4. mysql ssh .net_c# – 使用SSH.NET库与MySQL建立SSH连接
  5. osm数据导入mysql_OSM(OpenStreetMap) poi、路网 数据导入 PostgreSQL
  6. php7 configure 参数,PHP编译参数configure配置详解
  7. java jtable 单元格编辑_java – 在基于JTable面板的单元格编辑器中...
  8. 一个html页面上显示dopost,Java遇见HTML-servlet(一)
  9. linux中split分割文件打开方式,Linux系统下使用split命令分割大文件 (转载)
  10. asp实训报告摘要_个人网站实训报告---asp.NET 动态网站设计