Java 的双重分发与 Visitor 模式
双重分发(Double Dispatch)
什么是双重分发?
谈起面向对象的程序设计时,常说起的面向对象的「多态」,其中关于多态,经常有一个说法是「父类引用指向子类对象」。
这种父类的引用指向子类对象的写法类似下面这种:
Animal animal = new Dog();
animal.bark();
另一种常用的形式是
public class Keeper {
public void say(Animal a) {
System.out.println("Animal say");
}
public void say(Dog dog) {
System.out.println("dog say");
}
}
Animal animal = new Animal();
Animal dog = new Dog();
Keeper keeper = new Keeper();
keeper.say(animal);
keep.say(dog);
那上面的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(new ConcreateVisitor());
leaf.accept(new ConcreateVisitor());
node 中的 accept方法,会将自己的真实类型再次传递回visitor
public void accept(Visitor v) {
v.visit(this);
}
此时,在visitor中,就能根据真实的类型来调用具体的方法,对应node 和 leaf 分别有类似这样的方法:
public void visit(Node n);
public void visit(Leaf l);
Visitor 总结起来一般是包含 visitor 接口,在visitor 接口中,包含各个即将被访问的 Element对象的处理逻辑。在 各个Element 的具体实现中,再将自己的类型传递回visitor 进行二次分发,实现确切逻辑的调用。
在Tomcat中的应用
Visitor 在Tomcat中也有应用,典型的是解析EL表达式。
比如org.apache.el.parser.Node
这个类中包含一个accept(NodeVisitor visitor)方法
实际的 Node 类型有很多,但在真实调用的这个时候,会通过
public void accept(NodeVisitor visitor) throws Exception {
visitor.visit(this);
将真实类型传回visitor, vistor中会调用具体的方法,从而实现参数也能起到决定作用的功能。
public void visit(Node node) throws ELException {
if (node instanceof AstFunction) {
AstFunction funcNode = (AstFunction) node;
Method m = null;
} else if (xxx) {
}
这里一般会声明多个visit方法,然后上面的visit(this)会直接定位到目标方法上。
以上就是 Java 中的各类分发,以及 visitor这种模式通过模式的形式来实现双重分发的效果。
Java 的双重分发与 Visitor 模式的更多相关文章
- Java设计模式(21)访问模式(Visitor者模式)
Visitor定义:作用于某个对象群中各个对象的操作.它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作. 在Java中,Visitor模式实际上是分离了collection结构中的元 ...
- 《图解设计模式》读书笔记6-1 VISITOR模式
目录 1. Visitor模式简介 2. 示例 2.1 类图 2.2 代码 3. 模式的角色和类图 4. 思路拓展 4.1 双重分发 4.2 开闭原则 4.3 难以增加ConcreteElement角 ...
- Visitor模式,Decorator模式,Extension Object模式
Modem结构 Visitor模式 对于被访问(Modem)层次结构中的每一个派生类,访问者(Visitor)层次中都有一个对应的方法. 从派生类到方法的90度旋转. 新增类似的Windows配置函数 ...
- Visitor模式(访问者设计模式)
Visitor ? 在Visitor模式中,数据结构与处理被分离开来.我们编写一个表示"访问者"的类来访问数据结构中的元素, 并把对各元素的处理交给访问者类.这样,当需要增加新的处 ...
- java开发中的23中设计模式详解--大话设计模式
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- java开发中的23中设计模式
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- 设计模式之visitor模式,人人能懂的有趣实例
设计模式,现在在网上随便搜都一大堆,为什么我还要写"设计模式"的章节呢? 两个原因: 1.本人觉得这是一个有趣的设计模式使用实例,所以记下来: 2.看着设计模式很牛逼,却不知道怎么 ...
- Visitor 模式心得
最近读到Visitor模式,还是一知半解的.偶然翻到Uncle Bob对该模式的推导过程,有所心得,和大家分享一下. Uncle Bob 的链接是: http://butunclebob.com/Ar ...
- Java设计模式(22)命令模式(Command模式)
Command模式是最让我疑惑的一个模式,我在阅读了很多代码后,才感觉隐约掌握其大概原理,我认为理解设计模式最主要是掌握起原理构造,这样才对自己实际编程有指导作用.Command模式实际上不是个很具体 ...
随机推荐
- error:No buffer space available (maximum connections reached
2015-02-02 17:49:09,035 ERROR basic.DBManager - Failded to establish the connection. com.mysql.jdbc. ...
- shell脚本read -t 超时输入测试
[root@server0 shellStudy]# cat timeout.sh #!/bin/bash TIMEOUT=3 #超时间隔 echo "What is your name?& ...
- Struts1与Struts2的那些事
一.概述 Struts1以ActionServlet作为核心控制器,由ActionServlet负责拦截用户的全部请求.Struts1框架有3个重要组成部分:Action.ActionForm和Act ...
- 【转】 mysql反引号的使用(防冲突)
转载地址:http://blog.itechol.com/space.php?uid=33&do=blog&id=6681 1.mysql语句中 反引号 [`]作用: 避免表明.字段名 ...
- NFC手机上基于软件的卡模拟 重大利好还是安全噩梦?(转)
Software Card Emulation in NFC-enabled Mobile Phones: GreatAdvantage or Security Nightmare? Michael ...
- java.lang.IllegalArgumentException: Minimum column number is 0
easyUI的datagrid导出Excel时报如下错误: [2018-06-20 15:00:21] [ERROR] [org.jeecgframework.poi.excel.export.Exc ...
- hihocoder第220周-一道拧巴的题
一.220周 题目链接 问题描述 键盘上有N个数字按键,每个按键只能按一次,每次可以按下多个键,请输出所有可能的按键情况. 输入一个整数N(N在1~8之间),输出全部的按键可能.例如:输入3,输出为 ...
- vim recording功能介绍
使用vim时无意间触碰到q键,左下角出现“recording”这个标识,觉得好奇,遂在网上查了一下,然后这是vim的一个强大功能.他可以录制一个宏(Macro),在开始记录后,会记录你所有的键盘输入, ...
- nginx 实现valid_referer全面解析
先来补充点知识,然后在进行讲解. 先看下两种HTTP head 一个是直接输入网址打开的head,另一个是通过搜索引擎打开的网址head 一:直接输入网址打开的 (Request-Line) GET ...
- 利用图片中的exif元数据批量查找图片中所包含的GPS信息
在图片的exif(交换图像文件格式)中标准定义了如何存储图像和音频文件的标准,而在这些标签中往往存在了一些容易被人们忽视却又重要的东西. 有一款工具名为exiftool,可以快速的解析所有标签,并将结 ...