第一步:   在介绍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. 路由器基础配置之单臂路由实现vlan间通信

    我们将以上面的拓扑图开始进行配置,目的为设置单臂路由实现vlan间通信,设置4个vlan,pc0,1,2为vlan10 pc3,4,5为vlan20:pc6,7,8为vlan30:server0,1为 ...

  2. Oracle 11g R2在 win7 64位的安装流程图解【含常见问题解决方案】

    ORACLE数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一.Oracle 11 ...

  3. day1_作业2(三级菜单)--改进版

    #!/usr/local/bin/python3 # -*- coding:utf-8 -*- province={ '江苏省':{ '南京市':['秦淮区','玄武区','栖霞区'], '苏州市': ...

  4. windows系统下用VScode配置远程编辑服务器文件的环境!通过Rmate方法

    虽然公司电脑win可以通过Xshell通过SSH远程连接家中内网linux服务器了,但是只能用vim编辑文件有点不爽. 于是上网查询,windows下使用vscode远程编辑服务器文件的办法.参照博文 ...

  5. P1418 选点问题(黑白染色)

    P1418 选点问题 题目描述 给出n个点,m条边,每个点能控制与其相连的所有的边,要求选出一些点,使得这些点能控制所有的边,并且点数最少.同时,任意一条边不能被两个点控制 输入输出格式 输入格式: ...

  6. FastJson 打Release 包解析失败

    debug 的时候,fastJson 解析数据正常.但是打了release 的时候,解析的List 总是null. 找了半天,发现,是fastJson 是对泛型有问题. 解决办法: -keepattr ...

  7. com.squareup.okhttp.Interceptor

    retrift 集成了okhttp,所以,我们以后就不用再单独的引用http的jar 了. 但是,今天遇到一个问题,就是okhttp是这样设置一些intercept的: private static ...

  8. mongo创建数据库和用户

    1.linux安装mongo conf文件配置: 配置文件: dbpath=/home/data/mongodb/mongodb logpath=/home/data/logs/mongodb.log ...

  9. Hadoop 原理总结

    Hadoop 原理总结   一.Hadoop技术原理 Hdfs主要模块:NameNode.DataNode Yarn主要模块:ResourceManager.NodeManager 常用命令: 1)用 ...

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

    2014-03-21 22:05 题目:给你N个盒子堆成一座塔,要求下面盒子的长和宽都要严格大于上面的.问最多能堆多少个盒子? 解法1:O(n^2)的动态规划解决.其实是最长递增子序列问题,所以也可以 ...