浅谈Visitor Pattern
第一步: 在介绍Visitor Pattern (访问者模式)之前,先简要介绍一下:双重分派。
在Visitor Pattern中双重分派是指:数据结构的每一个节点都可以接受一个访问者的调用(这句话的代码是:在具体的节点类中有形如如下的方法accept(Visitor visitor){visitor.visitor(this)},说白一点就是,在节点类中有一个方法,以访问者作为参数,这个访问者也就是Visitor接口),此节点向访问者对象传入节点对象,而访问者对象反过来执行节点对象的操作。(这句话的代码是:在具体的访问者类中,有形如一个visitor(ConcreteNode node){node.operation()}的方法,说白点就是在Visitor接口中有益具体节点为参数的方法,有几个具体节点,就有几个方法)这样的过程就叫做双重分派。
第二步:介绍访问者模式所涉及的角色:
访问者模式的角色有6个,分别是:Visitor(抽象访问者) 、ConcreteVisitor(具体访问者)、Node(抽象节点),ConcreteNode(具体节点)、ObjectStructure(结构对象,你也可以翻译为对象结构,其实我更喜欢对象结构。)Client(客户,相当于一个测试类)
第三步:代码示例,把各个角色的代码抽象出来。
Visitor(抽象访问者)是一个接口或者,抽象类,其代码如下:
package com.qls.visitorPattern5;
public interface Visitor {
/**
* NodeA,NodeB分别是Node接口的两个具体实现类,
* 由于本例展示两个Node的具体实现类,所以Visitor接口中的抽象方法只有两个
* 一般而言:有多少个具体节点的实现类,在Visitor接口中就有多少个抽象方法。
* 这是因为:每一个具体的节点都有独一无二的业务方法(business method).
* @param node
*/
void visitor(NodeA node);
void visitor(NodeB node);
}
ConcreteVisitor(具体访问者)是Visitor的实现类,其代码如下:
第一个具体访问者的代码如下:
package com.qls.visitorPattern5;
public class VisitorA implements Visitor {
@Override
public void visitor(NodeA node) {
// TODO Auto-generated method stub
node.operation();//这个operation()是NodeA的特有的业务方法
}
@Override
public void visitor(NodeB node) {
// TODO Auto-generated method stub
node.operation();//这个operation()是NodeB的特有的业务方法
}
}
第二个具体访问者的代码如下:
package com.qls.visitorPattern5;
public class VisitorB implements Visitor {
@Override
public void visitor(NodeA node) {
// TODO Auto-generated method stub
node.operation();
}
@Override
public void visitor(NodeB node) {
// TODO Auto-generated method stub
node.operation();
}
}
Node(抽象节点)是一个接口,或者抽象类。是所有具体节点的基类.
package com.qls.vistitorPattern3;
/**
* 在Node接口中有以Visitor(抽象访问者)为参数的方法
* @author 秦林森
*
*/
public interface Node {
void accept(Visitor visitor);
}
ConcreteNode(具体节点)本例中有两个具体节点。
第一个具体节点的代码如下:
package com.qls.vistitorPattern3;
public class NodeA implements Node {
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
/**
* 这个this指代NodeA,其检验方法为:
* System.out.println("this 所指代的类是:"+this.getClass());
当我们不确定this,指代谁时,可以用这种方法进行检测。
*/
visitor.visitor(this);
}
//NodeA 所特有的业务方法或者称为商业方法
void operation(){
System.out.println("this is nodeA's operation");
}
}
第二个具体节点的代码如下:
package com.qls.vistitorPattern3;
public class NodeB implements Node {
/**
* 表示接受一个访问者。进行访问这个节点NodeB,执行NodeB所特有的业务方法。
*/
@Override
public void accept(Visitor visitor) {
// TODO Auto-generated method stub
visitor.visitor(this);
}
//NodeB 所特有的业务方法或者称为商业方法
void operation(){
System.out.println("this is nodeB's operation");
}
}
ObjectStructure(结构对象),这个角色的作用,以我个人的理解就是建立Visitor和Node关系的一个类。
其代码如下:
package com.qls.visitorPattern5;
import java.util.Enumeration;
import java.util.Vector;
public class ObjectStructure {
/**
* 一个容器用来存放Node,这个容器可以是ArrayList,Set等等不一定就非是Vector不可
*/
private Vector<Node> nodes;
private Node node;
public ObjectStructure() {
nodes=new Vector<Node>();
}
public void action(Visitor visitor){
Enumeration<Node> e = nodes.elements();
while(e.hasMoreElements()){
node = e.nextElement();
node.accept(visitor);//接受访问者,让访问者执行具体节点的相关操作。
}
}
/**
* 添加节点
* @param args
*/
public void add(Node node){
nodes.addElement(node);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
Client(客户)其作用就相当于一个测试类,把各个具体节点的业务方法的结果打印出来。
其代码如下:
package com.qls.visitorPattern5;
public class Client {
private static ObjectStructure objectStructure;
// private static Visitor visitor;
// private static Node node;
public static void main(String[] args) {
// TODO Auto-generated method stub
objectStructure=new ObjectStructure();//这步必须写,后者会报NullPointException
//添加一个节点
objectStructure.add(new NodeA());
objectStructure.add(new NodeB());
//创建一个访问者
objectStructure.action(new VisitorA());
//创建一个访问者
objectStructure.action(new VisitorB());
}
}
上述代码的运行结果为:由于我让两个访问者去访问ObjectStructure,具体节点的操作,是由具体访问者代劳的,所以运行结果为:
//前两句话是由objectStructure.action(new VisitorA());所产生的。
//后两句话是由:objectStructure.action(new VisitorB());所产生的。
this is nodeA's business method
this is NodeB's business method
this is nodeA's business method
this is NodeB's business method
浅谈Visitor Pattern的更多相关文章
- Android性能优化的浅谈
一.概要: 本文主要以Android的渲染机制.UI优化.多线程的处理.缓存处理.电量优化以及代码规范等几方面来简述Android的性能优化 二.渲染机制的优化: 大多数用户感知到的卡顿等性能问题的最 ...
- 浅谈OCR之Onenote 2010
原文:浅谈OCR之Onenote 2010 上一次我们讨论了Tesseract OCR引擎的用法,作为一款老牌的OCR引擎,目前已经开源,最新版本3.0中更是加入了中文OCR功能,再加上Google的 ...
- 【ASP.NET MVC系列】浅谈ASP.NET MVC 路由
ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...
- MYSQL优化浅谈,工具及优化点介绍,mysqldumpslow,pt-query-digest,explain等
MYSQL优化浅谈 msyql是开发常用的关系型数据库,快速.稳定.开源等优点就不说了. 个人认为,项目上线,标志着一个项目真正的开始.从运维,到反馈,到再分析,再版本迭代,再优化… 这是一个漫长且考 ...
- 浅谈ELK日志分析平台
作者:珂珂链接:https://zhuanlan.zhihu.com/p/22104361来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 小编的话 “技术干货”系列文章 ...
- 浅谈Log4j和Log4j2的区别
相信很多程序猿朋友对log4j都很熟悉,log4j可以说是陪伴了绝大多数的朋友开启的编程.我不知道log4j之前是用什么,至少在我的生涯中,是log4j带我开启的日志时代. log4j是Apache的 ...
- 浅谈.Net异步编程的前世今生----EAP篇
前言 在上一篇博文中,我们提到了APM模型实现异步编程的模式,通过使用APM模型,可以简化.Net中编写异步程序的方式,但APM模型本身依然存在一些缺点,如无法得知操作进度,不能取消异步操作等. 针对 ...
- 浅谈JavaScript中的正则表达式(适用初学者观看)
浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...
- 浅谈自底向上的Shell脚本编程及效率优化
作者:沐星晨 出处:http://blog.csdn.net/sosodream/article/details/6276758 浅谈自底向上的Shell脚本编程及效率优化 小论文,大家多批评指导:) ...
随机推荐
- js | javascript中获取dom元素的高度和宽度
javascript中获取dom元素高度和宽度的方法如下: 网页可见区域宽: document.body.clientWidth网页可见区域高: document.body.clientHeight网 ...
- Linux中用户与用户组管理
1.基础知识 Linux作为一种多用户的操作系统(服务器系统),允许多个用户同时登陆到系统上,并响应每个用户的请求. 任何需要使用操作系统的用户,都需要一个系统账号,账号分为:管理员账号与普通用户账号 ...
- python--Wrapper
然后给大家介绍的是Wrapper(装饰器),使用广泛.python笔试,面试的话也会百分百问到的,基础和中级的知识储备还是必用的. 让我们开始. 先来一些基础相关知识 *args,**kwargs的区 ...
- Python中的文件和目录操作实现
Python中的文件和目录操作实现 对于文件和目录的处理,虽然可以通过操作系统命令来完成,但是Python语言为了便于开发人员以编程的方式处理相关工作,提供了许多处理文件和目录的内置函数.重要的是,这 ...
- PLY手册翻译
https://www.kancloud.cn/kancloud/ply/42143 http://wiki.jikexueyuan.com/project/python-lex-yacc/ply-0 ...
- POJ 3662 (二分+SPFA
Telephone Lines Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8856 Accepted: 3211 D ...
- B-树 动机与结构
Ps.我们遵循从感性到理性的认知顺序来逐步探索B-树的奥秘,之前经常说的value这里用key(关键码)指代,因为可能存的是字符串,说是value就不合适了. (多图预警!!!建议在WI-FI下观看) ...
- urllib使用四--urlencode,urlparse,
urllib.urlencode 把字典数据转换为URL编码 # -*- coding: cp936 -*- import urllib params = {'score':100,'name':'爬 ...
- 初见spark-01
今天我们来学习spark,spark是一种快速,通用,可扩展的大数据分析引擎,现已成为Apache顶级项目,Spark是MapReduce的替代方案,而且兼容HDFS,Hive,可融入Hadoop的生 ...
- 2.栅格的类中同时设置col-md-* col-sm-*的作用
1.一般设定成这样的话,在小屏幕上会堆叠在一起 <div class="row"> <div class="col-md-4 ">COL ...