Double Dispatch讲解与实例

引言

说实话,我看过GoF《Design Patterns》,也曾深深的被李建忠《设计模式》系列Webcast。但是还没有见过“Double Dispatch模式”。的确GoF提及的设计模式只是最初对设计模式的系统介绍,它不可能涵盖所有的模式。另外随着时间的流逝,技术日新月异的变化,技术大牛们又总结出了许多新的模式。

今天所介绍的Double Dispatch模式,从时间上来看,已不是新的设计模式;但对于只看过GoF设计模式的技术同仁来说,也算是一个新的设计模式。

什么是DoubleDispatch?

对,没有“模式”二字。从字面翻译来看,网上好多人翻译为双分发,双分派。Wiki上对Double Dispatch的解释:

In software engineering, double dispatch is a special form of multiple dispatch, and a mechanism that dispatches a function call to different concrete functions depending on the runtime types of two objects involved in the call. In most object-oriented systems, the concrete function that is called from a function call in the code depends on the dynamic type of a single object and therefore they are known as single dispatch calls, or simply virtual function calls.

大意:

在软件工程中,Double Dispatch是一种特殊形式的Multiple Dispatch,也是根据于两个对象的运行时类型来调用的其相应具体类(不是基类)方法的一种机制。在大多数面向对象的系统中,在代码(程序)中的一个函数调用具体类的方法都取决于单个对象的动态类型(运行时的类型),(它们一般)被称为Single Dispath calls,或只是虚拟函数调用。

不难看出一次虚函数的调用叫做Single Dispath ,那么Double Dispatch应该就是两次虚函数的调用啦。

更进一步说就是一次通过动态类型(运行时类型)调用相应子类真实类型的方法函数,就称为一次Dispath。那么以此类推,需要两次通过运行时类型调用相应类型的方法函数,则称为Double Dispatch。

举例说明:

Single Dispatch 实例:

DoubDispatch 实例:

为啥要搞Double Dispatch?

输出结果

怎么没有输出“Dog Type”和“Mammals Type”呢?不对呀!!

怎么解决?

用Dynamic来解决

通过查阅关于函数重载决议相关的说明我们可以了解到:

重载是在编译时就决定了,所以无法在运行时动态决定。重写才是动态运行时决定的。

输出结果:

这样的解决虽然看起来解决了问题?但我不通过Double Dispatch 来实现的。只是通过了Dynamic。

用Vistor 模式来解决

总结

C# 现在引入Dynamic 来支持“Double Dispatch”,但我们应该清楚到底为什么要用这个关键字.

如果没有这个关键字,C#又是如何支持“Dobule Dispatch”的,这就是本篇所讲的目的。

更多关于Vistor内容,大家可自行百度谷歌。

后续我想写一篇关于Vistor的博客,还请大家多多支持!

参考

设计模式随笔-让众口不再难调

Software design pattern

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

关于双分派(Double Dispatch)的一点探讨(案例讲的很透彻,C++的代码)

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

Double dispatch in C#?

Dynamic Dispatch in C#

Acyclic Visitor模式:http://www.objectmentor.com/resources/articles/acv.pdf

Hierachical Visitor Pattern模式:http://en.wikipedia.org/wiki/Hierarchical_visitor_pattern

时间: 2024-10-16 15:06:59

Double Dispatch讲解与实例的相关文章

Object(所有类的超类)一些有用的方法讲解与实例演示

Object是所有类的始祖,java中的每个类的都是它拓展而来的. Object的euqals方法.hashCode方法.getClass方法和toString方法在操作对象时是非常有用的方法.     1.euqals方法      euqals方法用于检测一个对象是否等于另外一个对象(两个对象是否指向同一块存储区域),java语言规范要求euqals方法具有以下特性: 自反性.对称性.传递性.一致性并且对于任意的非空引用x,x.equals(null)应返回false. java7在java

linux CentOS 7 中LVM讲解配置实例及磁盘扩容等

一. lvm讲解 LVM是 Logical Volume Manager(逻辑卷管理)的简写,它由Heinz Mauelshagen在Linux 2.4内核上实现.LVM将一个或多个硬盘的分区在逻辑上集合,相当于一个大硬盘来使用,当硬盘的空间不够使用的时候,可以继续将其它的硬盘的分区加入其中,这样可以实现磁盘空间的动态管理,相对于普通的磁盘分区有很大的灵活性. 与传统的磁盘与分区相比,LVM为计算机提供了更高层次的磁盘存储.它使系统管理员可以更方便的为应用与用户分配存储空间.在LVM管理下的存储

iOS响应式编程框架ReactiveCocoa讲解与实例演示

Signal and Subscriber 这是RAC最核心的内容,如果用插头和插座来描述,插座是Signal,插头是Subscriber.插座负责去获取电,插头负责使用电,而且一个插座可以插任意数量的插头.当一个插座(Signal)没有插头 (Subscriber)时什么也不干,也就是处于冷(Cold)的状态,只有插了插头时才会去获取,这个时候就处于热(Hot)的状态. Signal获取到数据后,会调用Subscriber的sendNext, sendComplete, sendError方法

Future模式详细讲解及实例分析

1.1.Future模式是什么 先简单举个例子介绍,当我们平时写一个函数,函数里的语句一行行同步执行,如果某一行执行很慢,程序就必须等待,直到执行结束才返回结果:但有时我们可能并不急着需要其中某行的执行结果,想让被调用者立即返回.比如小明在某网站上成功创建了一个账号,创建完账号后会有邮件通知,如果在邮件通知时因某种原因耗时很久(此时账号已成功创建),使用传统同步执行的方式那就要等完这个时间才会有创建成功的结果返回到前端,但此时账号创建成功后我们并不需要立即关心邮件发送成功了没,此时就可以使用Fu

[ css 弹性盒子模型 flex-basis 属性 ] 弹性盒子模型flex布局中flex-basis属性讲解及实例演示的区别

设置或检索弹性盒伸缩基准值: 如果所有子元素的基准值之和大于剩余空间,则会根据每项设置的基准值,按比率伸缩剩余空间 计算值 – 绝对数:在flex-container主方向大小不足以容纳flex items的flex-basis总和时,浏览器会自动缩小它们 实例: <!DOCTYPE html> <html lang="zh-cmn-Hans"> <head> <meta charset="utf-8" /> <

[ css 外边距 margin ] css中margin外边距合并问题讲解及实例演示

外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距;合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者 外边距合并外边距合并(叠加)是一个相当简单的概念.但是,在实践中对网页进行布局时,它会造成许多混淆.简单地说,外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距.合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者.当一个元素出现在另一个元素上面时,第一个元素的下外边距与第二个元素的上外边距会发生合并.请看下图: CSS 外边距合并实例 1 亲自试一试

[ css 弹性盒子模型 align-content 属性 ] 弹性盒子模型flex布局中align-content属性讲解及实例演示的区别

说明: 本属性适用于:多行的弹性盒模型容器 当伸缩容器的侧轴还有多余空间时,本属性可以用来调准「伸缩行」在伸缩容器里的对齐方式,这与调准伸缩项目在主轴上对齐方式的 <' justify-content '> 属性类似.请注意本属性在只有一行的伸缩容器上没有效果 实例: <!DOCTYPE html> <html lang="zh-cmn-Hans"> <head> <meta charset="utf-8" /&

[ css 弹性盒子模型 align-item 属性 ] 弹性盒子模型flex布局中align-item属性讲解及实例演示的区别

说明: 本属性适用于:flex容器 定义flex子项在flex容器的当前行的侧轴(纵轴)方向上的对齐方式 实例: <!DOCTYPE html> <html lang="zh-cmn-Hans"> <head> <meta charset="utf-8" /> <title>align-items_CSS参考手册_web前端开发参考手册系列</title> <meta name="

python之threading模块简单讲解和实例演示

import threading 在处理一些程序时为了节约时间,可以使用多线程的方式, 让其并发去执行,从而节约时间, (注意python其实是伪多线程,其实是以我们感觉不到的速度每行代码都按照相同时间执行) Lock 当多线程同时对一个变量进行修改操作的时候,那么可能会出现混乱, 因为其是并发(算是吧)而行, (所以当两个赋值时间相对接近时那么其容易出现混乱) 所以我们得创建锁, 让其上一个线程赋值结束, 下一个赋值再继续 threading.Lock() 创建锁 是可用的最低级的同步指令.