- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java 的双重分发与 Visitor 模式实例详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
双重分发(double dispatch) 。
什么是双重分发?
谈起面向对象的程序设计时,常说起的面向对象的「多态」,其中关于多态,经常有一个说法是「父类引用指向子类对象」.
这种父类的引用指向子类对象的写法类似下面这种:
1
2
|
animal animal =
new
dog();
animal.bark();
|
另一种常用的形式是 。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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 ,执行不同的内容.
代码类似这样:
1
2
|
node.accept(
new
concreatevisitor());
leaf.accept(
new
concreatevisitor());
|
node 中的 accept方法,会将自己的真实类型再次传递回visitor 。
1
2
3
|
public
void
accept(visitor v) {
v.visit(
this
);
}
|
此时,在visitor中,就能根据真实的类型来调用具体的方法,对应node 和 leaf 分别有类似这样的方法:
1
2
|
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 类型有很多,但在真实调用的这个时候,会通过 。
1
2
|
public
void
accept(nodevisitor visitor)
throws
exception {
visitor.visit(
this
);
|
将真实类型传回visitor, vistor中会调用具体的方法,从而实现参数也能起到决定作用的功能.
1
2
3
4
5
6
7
|
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这种模式通过模式的形式来实现双重分发的效果。希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的! 。
原文链接:http://zhuanlan.51cto.com/art/201807/578177.htm 。
最后此篇关于Java 的双重分发与 Visitor 模式实例详解的文章就讲到这里了,如果你想了解更多关于Java 的双重分发与 Visitor 模式实例详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
对此感到疯狂,真的缺少一些东西。 我有webpack 4.6.0,webpack-cli ^ 2.1.2,所以是最新的。 在文档(https://webpack.js.org/concepts/mod
object Host "os.google.com" { import "windows" address = "linux.google.com" groups = ["linux"] } obj
每当我安装我的应用程序时,我都可以将数据库从 Assets 文件夹复制到 /data/data/packagename/databases/ .到此为止,应用程序工作得很好。 但 10 或 15 秒后
我在 cc 模式缓冲区中使用 hideshow.el 来折叠我不查看的文件部分。 如果能够在 XML 文档中做到这一点就好了。我使用 emacs 22.2.1 和内置的 sgml-mode 进行 xm
已结束。此问题不符合 Stack Overflow guidelines .它目前不接受答案。 我们不允许提出有关书籍、工具、软件库等方面的建议的问题。您可以编辑问题,以便用事实和引用来回答它。 关闭
根据java: public Scanner useDelimiter(String pattern) Sets this scanner's delimiting pattern to a patt
我读过一些关于 PRG 模式以及它如何防止用户重新提交表单的文章。比如this post有一张不错的图: 我能理解为什么在收到 2xx 后用户刷新页面时不会发生表单提交。但我仍然想知道: (1) 如果
看看下面的图片,您可能会清楚地看到这一点。 那么如何在带有其他一些 View 的简单屏幕中实现没有任何弹出/对话框/模式的微调器日期选择器? 我在整个网络上进行了谷歌搜索,但没有找到与之相关的任何合适
我不知道该怎么做,我一直遇到问题。 以下是代码: rows = int(input()) for i in range(1,rows): for j in range(1,i+1):
我想为重写创建一个正则表达式。 将所有请求重写为 index.php(不需要匹配),它不是以/api 开头,或者不是以('.html',或'.js'或'.css'或'.png'结束) 我的例子还是这样
MVC模式代表 Model-View-Controller(模型-视图-控制器) 模式 MVC模式用于应用程序的分层开发 Model(模型) - 模型代表一个存取数据的对象或 JAVA PO
我想为组织模式创建一个 RDF 模式世界。您可能知道,组织模式文档基于层次结构大纲,其中标题是主要的分组实体。 * March auxiliary :PROPERTIES: :HLEVEL: 1 :E
我正在编写一个可以从文件中读取 JSON 数据的软件。该文件包含“person”——一个值为对象数组的对象。我打算使用 JSON 模式验证库来验证内容,而不是自己编写代码。符合代表以下数据的 JSON
假设我有 4 张 table 人 公司 团体 和 账单 现在bills/persons和bills/companys和bills/groups之间是多对多的关系。 我看到了 4 种可能的 sql 模式
假设您有这样的文档: doc1: id:1 text: ... references: Journal1, 2013, pag 123 references: Journal2, 2014,
我有这个架构。它检查评论,目前工作正常。 var schema = { id: '', type: 'object', additionalProperties: false, pro
这可能很简单,但有人可以解释为什么以下模式匹配不明智吗?它说其他规则,例如1, 0, _ 永远不会匹配。 let matchTest(n : int) = let ran = new Rand
我有以下选择序列作为 XML 模式的一部分。理想情况下,我想要一个序列: 来自 my:namespace 的元素必须严格解析。 来自任何其他命名空间的元素,不包括 ##targetNamespace和
我希望编写一个 json 模式来涵盖这个(简化的)示例 { "errorMessage": "", "nbRunningQueries": 0, "isError": Fals
首先,我是 f# 的新手,所以也许答案很明显,但我没有看到。所以我有一些带有 id 和值的元组。我知道我正在寻找的 id,我想从我传入的三个元组中选择正确的元组。我打算用两个 match 语句来做到这
我是一名优秀的程序员,十分优秀!