Java 的双重分发与 Visitor 模式

作者 : 开心源码 本文共1404个字,预计阅读时间需要4分钟 发布时间: 2022-05-12 共57人阅读

双重分发(Double Dispatch)

什么是双重分发?

谈起面向对象的程序设计时,常说起的面向对象的「多态」,其中关于多态,经常有一个说法是「父类引使用指向子类对象」。

这种父类的引使用指向子类对象的写法相似下面这种:

另一种常使用的形式是

那上面的keeper调使用两次say的时候,会输出什么内容呢?会调使用到两个不同的方法吗?

实际上在这两次调使用的时候,都会调使用到say(Animal a)这个方法。因为这些内容在编译期就能的确下来,这就是 Java 的静态分发

从上面的图我们看到,对于两次调使用生成的字节码,的确都指向了say(Animal a)这个方法,运行时直接执行方法,输出了对应的内容。

那对应的animal.bark()为什么最终会调使用到 dog 类的方法?这是在运行时确定具体的方法接收者的类型并执行。这就是所谓的动态分发,在运行时确定具体的方法,实现面向对象的多态

分发(Dispatch)

分发就是指最终确定一个要执行的方法的过程。

对于 Java 等静态语言来说,都是通过 单一分发(Single Dispatch)来进行的方法执行。

比方这样一行代码

dog.eat(new Bone())

最终执行要选择的eat方法,只会根据dog的具体类型选择到对应的方法,而传入的参数并不能影响到对应方法的选择,这种就是single Dispatch

为了让传入的真实参数,这里就是Bone来真正起到作使用,就需要使用到Double Dispatch或者者叫做Multiple Dispatch

也就是说最终决定调使用方法是哪一个的,不仅仅是方法的接收者,还受参数类型的决定。

Visitor 模式

在GoF 的设计模式中,Visitor 模式就用到了Double Dispatch达到了调使用真实对象的目的。

对于Visitor模式,最常使用的例子是树的遍历。比方在解决到节点和树叶时的方式有区别,此归通过 visitor 的双重分发,实现对于不同的 Element ,执行不同的内容。

代码相似这样:

node 中的?accept方法,会将自己的真实类型再次传递回visitor

此时,在visitor中,就能根据真实的类型来调使用具体的方法,对应node 和 leaf 分别有相似这样的方法:

Visitor 总结起来一般是包含 visitor 接口,在visitor 接口中,包含各个即将被访问的 Element对象的解决逻辑。在 各个Element 的具体实现中,再将自己的类型传递回visitor 进行二次分发,实现确切逻辑的调使用。

在Tomcat中的应使用

Visitor 在Tomcat中也有应使用,典型的是解析EL表达式。

比方org.apache.el.parser.Node

这个类中包含一个accept(NodeVisitor visitor)方法

实际的 Node 类型有很多,但在真实调使用的这个时候,会通过

将真实类型传回visitor, vistor中会调使用具体的方法,从而实现参数也能起到决定作使用的功能。

这里一般会公告多个visit方法,而后上面的visit(this)会直接定位到目标方法上。

以上就是 Java 中的各类分发,以及 visitor这种模式通过模式的形式来实现双重分发的效果。

欢迎工作一到五年的Java工程师朋友们加入Java架构开发:744677563

本群提供免费的学习指导 架构资料 以及免费的解答

不懂得问题都可以在本群提出来 之后还会有职业生涯规划以及面试指导

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Java 的双重分发与 Visitor 模式

发表回复