设计模式-访问者(Visitor)模式
访问者模式是对象的行为模式。访问者模式的目的是封装施加在某种数据结构元素上的操作。一旦一些操作需要修改,接受这个操作的数据结构可以保持不变。
个人觉得访问者模式相对其他的设计模式来说稍微复杂,难理解一点,要理解这个模式首先需要了解“单分派与多分派”。
单分派与多分派
根据对象的类型对执行方法进行选择,就是分派(Dispatch)。分派是面向对象语言提供的关键特性之一,根据分派发生的时期,可分为两种,静态分派和动态分派。静态分派发生在编译时期,动态分派发生在执行时期。
重载方法的分派是根据静态类型进行的,分派过程发生在编译时期,属于静态分派。
Java通过Override重写来支持动态分派,Java编译器并不会知道执行阶段会执行哪段重写的方法。
Java语言支持静态的多分派和动态的单分派,分别是通过重载方法和重写方式实现的。
Java语言通过两个宗量来决定执行哪一段代码:
方法的接受者:也即方法执行的对象,方法的接受者,动态分派根据具体类型决定;
事件对象:一个类行为的对象,传输的参数类型。
而访问者模式就是通过重写和重载的结合使用来达到实现双重分派的目的。
访问者模式
下面结合我们实际项目中的需求来阐述一下访问者模式。
访问者模式的类图如下:

所涉及到的角色:
抽象访问者:声明一个或多个访问操作,形成所有的具体元素角色必须实现的接口。下面的示例就是资源访问操作的顶层接口。
public interface IResourceVisitor {
//detail resource
void visit(JavaClassResource resource) throws ResourceParserException;
void visit(MetadataResource resource) throws ResourceParserException;
void visit(UpmResource resource) throws ResourceParserException;
void visit(XmlResource resource) throws ResourceParserException;
void visit(PropertiesResource propertiesResource) throws ResourceParserException;
//composite resource
void visit(BusinessComponentResource resource) throws ResourceParserException;
void visit(JavaClassSrcResource resource) throws ResourceParserException;
具体访问者:实现抽象访问者角色所声明的接口,就是抽象访问所声明的各个访问操作。一般情况下,由于一般情况下抽象访问者的方法都比较多,而且具体访问者也不会关心抽象访问者的所有方法,因此通常有一个默认的实现Adaptor介于两者之间。
Adaptor也是一个非常重要的类,对于Composite类型的资源,存在一个默认遍历策略。
public abstract class AbstractResourceVisitorAdaptor implements IResourceVisitor {
@Override
public void visit(JavaClassResource resource) throws ResourceParserException {
}
@Override
public void visit(MetadataResource resource) throws ResourceParserException {
}
@Override
public void visit(UpmResource resource) throws ResourceParserException {
}
@Override
public void visit(XmlResource resource) throws ResourceParserException {
}
@Override
public void visit(PropertiesResource propertiesResource) throws ResourceParserException {
}
@Override
public final void visit(BusinessComponentResource resource) throws ResourceParserException {
visitComposite(resource);
}
protected final void visitComposite(CompositeResource compositeResource) throws ResourceParserException {
List<IResource> subResources = compositeResource.getSubResources();
for (IResource subResource : subResources) {
subResource.accept(this);
}
}
}
抽象节点:声明一个接受操作,接受一个访问者对象作为一个参量。
public interface IResource {
/**
* Visitor mode to access resources.
*
* @param resourceVisitor
*/
void accept(IResourceVisitor resourceVisitor) throws ResourceParserException;
}
具体节点:实现抽象元素规定的accept操作,通常这个接口的层次结构反映了整个程序的数据结构。

结构对象: 结构对象可以遍历结构中的所有元素,如果需要,提供一个高层次的接口让访问者对象能够访问每一个元素;如果需要,可以设计成复合对象或一个聚集。
最终的UML类图结构如下所示(已隐藏过多的实现):

使用场景
访问者模式提供了一种倾斜的可扩展性,仅在当被访问的类结构非常稳定的时候使用(就比如PMD的类库中对Java代码结构进行了分析,Java类的结构语法相对来说非常稳定,其使用的就是访问者模式)。系统应该很少出现需要加入新节点的情况。其倾斜的可扩展性体现在:方法集合的可扩展性和类集合的不可扩展性。
设计模式-访问者(Visitor)模式的更多相关文章
- 设计模式之visitor模式,人人能懂的有趣实例
设计模式,现在在网上随便搜都一大堆,为什么我还要写"设计模式"的章节呢? 两个原因: 1.本人觉得这是一个有趣的设计模式使用实例,所以记下来: 2.看着设计模式很牛逼,却不知道怎么 ...
- 设计模式之——visitor模式
visitor模式,又叫访问者模式,把结构和数据分开,编写一个访问者,去访问数据结构中的元素,然后把对各元素的处理全部交给访问者类.这样,当需要增加新的处理时候,只需要编写新的 访问者类,让数据结构可 ...
- 设计模式C++描述----22.访问者(Visitor)模式
一. 访问者模式 定义:表示一个作用于某对象结构中的各元素的操作.它你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 结构如下: 二. 举例 假设有一项科学实验,是用来对比两种种子在不同环 ...
- [设计模式]访问者 Visitor 模式
访问者模式是对象的行为模式. 访问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变.
- 设计模式之Visitor模式(笔记)
訪问者模式:表示一个作用于某个对象结构中的各元素操作.它使你能够不改变各元素的类的前提下定义作用于这些元素的新操作. 首先定义一个visitor抽象类,为每一个详细类声明一个visit操作 publi ...
- 设计模式:visitor模式
核心:将数据结构和数据的处理分开 注意:注意函数的参数传递和调用关系 例子: class Element; class Visitor { public: virtual void Visit(Ele ...
- 设计模式 -- 访问者模式(Visitor)
写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------主要内容包括: 初识访问者模 ...
- Visitor模式(访问者设计模式)
Visitor ? 在Visitor模式中,数据结构与处理被分离开来.我们编写一个表示"访问者"的类来访问数据结构中的元素, 并把对各元素的处理交给访问者类.这样,当需要增加新的处 ...
- .NET设计模式访问者模式
一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该 ...
随机推荐
- iOS 可能用到的三方框架
1.MWPhotoBrowser 第三方图片浏览器 https://github.com/mwaterfall/MWPhotoBrowser 2.SlackTextViewController 强大 ...
- 将VS2010环境设置为VC6.0样式(字体、前景色、背景色、Visual Assist X等)
一.设置字体. 使用字体:Fixedsys Excelsior 3.01. 步骤1:下载字体. 步骤2:安装字体,控制面板->字体,复制下载的字体进去. 步骤3:打开VS2010,选择菜单:To ...
- is7.0中发布mvc网站,一直无法正常执行路由的解决办法
在config中加一句话: <system.webServer> <validation validateIntegratedModeConfiguration="fals ...
- Linux之LVM设备的管理
LVM可以理解为可扩展的设备:在设备空间不足的时候,保证其在原始数据不变的情况下增大设备的存储大小.那么,要达到这种效果,我们得把可用设备先比变为物理卷,再把物理卷处理为物理卷组,最后成为LVM逻辑卷 ...
- TF随笔-10
#!/usr/bin/env python# -*- coding: utf-8 -*-import tensorflow as tf x = tf.constant(2)y = tf.constan ...
- FairyGUI编辑器制作Unity3D UI值得借鉴
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...
- MySQL基础(《MySQL必知必会》简单总结)
使用MySQL # 选择数据库 USE database_name; # 显示数据库 SHOW DATABASES; # 显示当前数据库的表 SHOW TABLES; # 显示特定表有哪些列 SHOW ...
- 轻量级KVO[译]
在这篇文章中,我会实现一个自己用的简单KVO类,我认为KVO非常棒,然而对于我大部分的使用场景来说,有这两个问题: 1. 我不喜欢在observeValueForKeyPath:ofObjec ...
- Java 按行拆分txt
T028619630|@|聚二零|@|M|@|1983-01-01|@|0|@|110101198301010098|@||@||@||@|湖南省衡阳市耒阳市蔡伦步行街1005号302|@|42100 ...
- LeetCode Find Permutation
原题链接在这里:https://leetcode.com/problems/find-permutation/description/ 题目: By now, you are given a secr ...