Java 的双重分发与 Visitor 模式

简介: 双重分发(Double Dispatch)什么是双重分发?谈起面向对象的程序设计时,常说起的面向对象的「多态」,其中关于多态,经常有一个说法是「父类引用指向子类对象」。

双重分发(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

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

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

相关文章
|
3月前
|
存储 Java 开发者
【Java新纪元启航】JDK 22:解锁未命名变量与模式,让代码更简洁,思维更自由!
【9月更文挑战第7天】JDK 22带来的未命名变量与模式匹配的结合,是Java编程语言发展历程中的一个重要里程碑。它不仅简化了代码,提高了开发效率,更重要的是,它激发了我们对Java编程的新思考,让我们有机会以更加自由、更加创造性的方式解决问题。随着Java生态系统的不断演进,我们有理由相信,未来的Java将更加灵活、更加强大,为开发者们提供更加广阔的舞台。让我们携手并进,共同迎接Java新纪元的到来!
74 11
|
3月前
|
设计模式 Java
Java设计模式-工厂方法模式(4)
Java设计模式-工厂方法模式(4)
|
4月前
|
消息中间件 Java
【实战揭秘】如何运用Java发布-订阅模式,打造高效响应式天气预报App?
【8月更文挑战第30天】发布-订阅模式是一种消息通信模型,发送者将消息发布到公共队列,接收者自行订阅并处理。此模式降低了对象间的耦合度,使系统更灵活、可扩展。例如,在天气预报应用中,`WeatherEventPublisher` 类作为发布者收集天气数据并通知订阅者(如 `TemperatureDisplay` 和 `HumidityDisplay`),实现组件间的解耦和动态更新。这种方式适用于事件驱动的应用,提高了系统的扩展性和可维护性。
81 2
|
4月前
|
Java
"揭秘Java IO三大模式:BIO、NIO、AIO背后的秘密!为何AIO成为高并发时代的宠儿,你的选择对了吗?"
【8月更文挑战第19天】在Java的IO编程中,BIO、NIO与AIO代表了三种不同的IO处理机制。BIO采用同步阻塞模型,每个连接需单独线程处理,适用于连接少且稳定的场景。NIO引入了非阻塞性质,利用Channel、Buffer与Selector实现多路复用,提升了效率与吞吐量。AIO则是真正的异步IO,在JDK 7中引入,通过回调或Future机制在IO操作完成后通知应用,适合高并发场景。选择合适的模型对构建高效网络应用至关重要。
94 2
|
4月前
|
设计模式 XML 存储
【二】设计模式~~~创建型模式~~~工厂方法模式(Java)
文章详细介绍了工厂方法模式(Factory Method Pattern),这是一种创建型设计模式,用于将对象的创建过程委托给多个工厂子类中的某一个,以实现对象创建的封装和扩展性。文章通过日志记录器的实例,展示了工厂方法模式的结构、角色、时序图、代码实现、优点、缺点以及适用环境,并探讨了如何通过配置文件和Java反射机制实现工厂的动态创建。
【二】设计模式~~~创建型模式~~~工厂方法模式(Java)
|
4月前
|
设计模式 XML Java
【一】设计模式~~~创建型模式~~~简单工厂模式(Java)
文章详细介绍了简单工厂模式(Simple Factory Pattern),这是一种创建型设计模式,用于根据输入参数的不同返回不同类的实例,而客户端不需要知道具体类名。文章通过图表类的实例,展示了简单工厂模式的结构、时序图、代码实现、优缺点以及适用环境,并提供了Java代码示例和扩展应用,如通过配置文件读取参数来实现对象的创建。
【一】设计模式~~~创建型模式~~~简单工厂模式(Java)
|
3月前
|
JSON Java UED
uniapp:使用DCloud的uni-push推送消息通知(在线模式)java实现
以上展示了使用Java结合DCloud的uni-push进行在线消息推送的基本步骤和实现方法。实际部署时,可能需要依据实际项目的规模,业务场景及用户基数进行必要的调整和优化,确保消息推送机制在保证用户体验的同时也满足业务需求。
235 0
|
5月前
|
设计模式 监控 Java
Java中的并发编程模式与最佳实践
随着多核处理器的普及,充分利用并发和多线程成为提高软件性能的关键。Java语言通过其丰富的并发API提供了强大的支持,使得开发者能够构建高效、可靠的并发应用程序。本文深入探讨了Java并发编程的核心概念、设计模式以及在实际开发中的最佳实践,旨在帮助读者更好地理解和掌握Java并发编程,从而编写出更加高效、稳定的应用程序。
|
5月前
|
设计模式 Java 开发者
Java中的异常处理与断路器模式
Java中的异常处理与断路器模式
|
6月前
|
消息中间件 存储 负载均衡
Java中的异步消息传递模式
Java中的异步消息传递模式