本节应用命令模式,在Java中模拟双分派。理解本节后,访问者模式(visitor pattern)手到擒来。
1. 单分派
分派/ dispatch是指如何给一个消息绑定其方法体。Java、C#等仅仅支持单分派(singledispatch)而不支持双分派(double dispatch)。【相关概念,参考《设计模式.5.11访问者模式》p223】
对于消息a.foo(b),假设有父类X及其两个子类X1、X2,a声明为X类型变量;有父类Y及其两个子类Y1、Y2,b声明为Y类型变量,而且X、X1和X2都各自准备了foo(Y)、foo(Y1)和foo(Y2)方法,请问a.foo(b)将执行的方法体是3*3=9个方法中的哪一个?
当前主流的面向对象语言如C++、Java、C#等,仅仅支持单分派(singledispatch)。例程3-18中,目前可以不管a.foo(b)中的参数b,我们仅仅看消息a.m()好了。假定X、X1和X2都各自准备了m(),则a.m()按照a的实际类型绑定其override的方法体,这就是面向对象中的动态绑定。
所谓的双分派,则是希望a.foo(b)能够①按照a的实际类型绑定其override的方法体,而且能够②按照b的实际类型绑定其重载的方法即foo(Y)、foo(Y1)、foo(Y2)中的适当方法体。显然,Java不支持后者——即不支持双分派。Java在编译时,就为foo(b)按照b的声明类型静态绑定了foo(Y)这个的方法体。Java重载方法的匹配算法,请参考【编程导论·2.3.1】。
例程 3 18 单分派
package mand.doubleDispatch;
import static tool.Print.*;