GoF著作中未提到的设计模式(4):Double Dispatch
我们先从字面上去理解它吧,直观地说,它指的是两次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相关推荐
- Java开发中的23种设计模式详解(转)
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- 如何丢弃Git中未进行的变更?
如何丢弃工作副本中未包含在索引中的更改? #1楼 这会签出当前目录的当前索引,从而丢弃文件从当前目录向下的所有更改. git checkout . 或此操作从索引中检出所有文件,覆盖工作树文件. gi ...
- 【java】java开发中的23种设计模式详解
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- [Google Guava] 2.3-强大的集合工具类:java.util.Collections中未包含的集合工具
原文链接 译文链接 译者:沈义扬,校对:丁一 尚未完成: Queues, Tables工具类 任何对JDK集合框架有经验的程序员都熟悉和喜欢java.util.Collections包含的工具方法.G ...
- Java中的中介器设计模式-示例教程
中介者模式是行为设计模式之一 ,因此它处理对象的行为. 中介器设计模式用于在系统中不同对象之间提供集中式通信介质. 根据GoF,中介者模式意图是: 通过封装不同对象集相互交互和通信的方式,允许松散耦合 ...
- Java开发中的23种设计模式详解
设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...
- 【设计模式】谈谈我们工作中的23个设计模式
ID 标题 地址 1 设计模式面试题(总结最全面的面试题) https://writer.blog.csdn.net/article/details/127910080 2 Java基础知识面试题(总 ...
- java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...
23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...
- 实战!工作中常用到哪些设计模式
前言 平时我们写代码呢,多数情况都是流水线式写代码,基本就可以实现业务逻辑了.如何在写代码中找到乐趣呢,我觉得,最好的方式就是:使用设计模式优化自己的业务代码.今天跟大家聊聊日常工作中,我都使用过哪些 ...
最新文章
- ethereumjs/ethereumjs-util
- SAP系统中设备管理模块的主要增强出口
- 在Visual Studio中使用用例图描述系统与参与者间的关系
- Test live writer
- ASP.NET 构建高性能网站 架构设计
- 第5课 开心的金明《聪明人的游戏:信息学探秘.提高篇》
- MYSQL 表 部分数据导出、导入
- 异常的分类 java 1615309080
- Linux下 sshd服务不能启动
- java 内部类序列化_Gson如何序列化内部类
- 程序设计 关键字解释
- java newtonsoft.json_Newtonsoft.Json 的序列化与反序列化
- mysql 高可用架构 proxysql 之一 yum安装
- Image Upload based on jQuery
- h5页面编写注意事项,自己遇到的小问题。
- Java多组输入实现 C++多组输入实现
- 离散小波变换wavedec matlab,MATLAB小波变换指令及其功能介绍(超级有用)
- 郭盛华:互联网安全可能是下一个热门投资主题
- 关于获取日周月的时间处理与日期联动处理
- 入门级练习题(1-15)
热门文章
- Web 2.0与云计算
- php获得每个月第一天的时间,PHP获取指定日期所在月的第一天和最后一天几个例子...
- 实验楼python挑战答案_python基础知识
- mysql ssh .net_c# – 使用SSH.NET库与MySQL建立SSH连接
- osm数据导入mysql_OSM(OpenStreetMap) poi、路网 数据导入 PostgreSQL
- php7 configure 参数,PHP编译参数configure配置详解
- java jtable 单元格编辑_java – 在基于JTable面板的单元格编辑器中...
- 一个html页面上显示dopost,Java遇见HTML-servlet(一)
- linux中split分割文件打开方式,Linux系统下使用split命令分割大文件 (转载)
- asp实训报告摘要_个人网站实训报告---asp.NET 动态网站设计