第一步:   在介绍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的更多相关文章

  1. Android性能优化的浅谈

    一.概要: 本文主要以Android的渲染机制.UI优化.多线程的处理.缓存处理.电量优化以及代码规范等几方面来简述Android的性能优化 二.渲染机制的优化: 大多数用户感知到的卡顿等性能问题的最 ...

  2. 浅谈OCR之Onenote 2010

    原文:浅谈OCR之Onenote 2010 上一次我们讨论了Tesseract OCR引擎的用法,作为一款老牌的OCR引擎,目前已经开源,最新版本3.0中更是加入了中文OCR功能,再加上Google的 ...

  3. 【ASP.NET MVC系列】浅谈ASP.NET MVC 路由

    ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...

  4. MYSQL优化浅谈,工具及优化点介绍,mysqldumpslow,pt-query-digest,explain等

    MYSQL优化浅谈 msyql是开发常用的关系型数据库,快速.稳定.开源等优点就不说了. 个人认为,项目上线,标志着一个项目真正的开始.从运维,到反馈,到再分析,再版本迭代,再优化… 这是一个漫长且考 ...

  5. 浅谈ELK日志分析平台

    作者:珂珂链接:https://zhuanlan.zhihu.com/p/22104361来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 小编的话 “技术干货”系列文章 ...

  6. 浅谈Log4j和Log4j2的区别

    相信很多程序猿朋友对log4j都很熟悉,log4j可以说是陪伴了绝大多数的朋友开启的编程.我不知道log4j之前是用什么,至少在我的生涯中,是log4j带我开启的日志时代. log4j是Apache的 ...

  7. 浅谈.Net异步编程的前世今生----EAP篇

    前言 在上一篇博文中,我们提到了APM模型实现异步编程的模式,通过使用APM模型,可以简化.Net中编写异步程序的方式,但APM模型本身依然存在一些缺点,如无法得知操作进度,不能取消异步操作等. 针对 ...

  8. 浅谈JavaScript中的正则表达式(适用初学者观看)

    浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...

  9. 浅谈自底向上的Shell脚本编程及效率优化

    作者:沐星晨 出处:http://blog.csdn.net/sosodream/article/details/6276758 浅谈自底向上的Shell脚本编程及效率优化 小论文,大家多批评指导:) ...

随机推荐

  1. Redis数据库 : python与java操作redis

    redis 包 from redis import * 连接: r = StrictRedis(host='localhost', port='6379') 读写:r.set('key','value ...

  2. python——标准异常总结

    请参考此网站: Python 标准异常总结 https://fishc.com.cn/forum.php?mod=viewthread&tid=45814&extra=page%3D1 ...

  3. PHP代码审计2-常用超全局变量,常用命令注入,常用XSS漏洞审计,文件包含

    超全局变量 $GLOBALS — 引用全局作用域中可用的全部变量$_SERVER — 服务器和执行环境信息$_GET — HTTP GET 变量$_POST — HTTP POST 变量$_FILES ...

  4. Service Intent must be explicit

    参考: http://blog.csdn.net/qs_csu/article/details/45114251 我做阿里云账号登录的时候,遇到一个问题,不知道阿里云服务的包名.怎么办?第二种方法可以 ...

  5. Android学习记录(2)—Android中数据库的常见操作

    android中数据库操作是非常常见了,我们会经常用到,操作的方法也有很多种形式,这里我就把最常见的两种形式记录下来了,以备以后用到方便查看.我就不写注释和解释了,因为android数据库的操作和其它 ...

  6. 《Cracking the Coding Interview》——第11章:排序和搜索——题目4

    2014-03-21 21:28 题目:给定一个20GB大小的文本文件,每一行都是一个字符串.请设计方法将这个文件里的字符串排序. 解法:请看下面的注释. 代码: // 11.4 Given a fi ...

  7. 用gulp清除、移动、压缩、合并、替换代码

    之前前端代码部署时用的是grunt,后来又出了个gulp工具,最近试用了一下,很方便,感觉比grunt简单好用,下面把一些常见的任务列一下,备用. var gulp = require('gulp') ...

  8. 自动化测试环境搭建--Python及selenium

    安装pyhton 访问Python官网:http://www.python.org 下载页Windows下找到适合64位系统的版本 下载后双击安装 安装后查看计算机->属性->高级系统设置 ...

  9. typeAliasesPackage 配置

    mybatis 的 xml 文件中需要写类的全限定名,较繁琐,可以配置自动扫描包路径给类配置别名,有两种配置方式. 方式一: mybatis-config.xml 中配置 <typeAliase ...

  10. CS/BS架构的特点

    CS架构 优点: 1.有独立的客户端,安全性高 2.大部分业务都在客户端实现,可以实现很复杂的业务 缺点: 1.对环境要求高,需要安装客户端,推广速度慢 2.需要专门前后台的开发团队,维护成本高 B/ ...