第一步:   在介绍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. springMVC集成logback日志系统

    一.项目结构 项目介绍:maven搭建的web项目,实现Java日志记录功能.其中logback.xml为日志配置文件,spring-mvc-servlet.xml为spring controller ...

  2. iOS-重构微博cell模型

    一.Frame模型: -------------------WeiboFrame.h-------------------------------------------------- ------- ...

  3. Codeforces Round #462 (Div. 2) C DP

    C. A Twisty Movement time limit per test 1 second memory limit per test 256 megabytes input standard ...

  4. Description POJ1703

    Description The police office in Tadu City decides to say ends to the chaos, as launch actions to ro ...

  5. html_outputer.py

    coding=UTF-8 # HTML输出器 import sys class htmlOutputer(): def __init__(self): self.data = [] def colle ...

  6. Android+Handler+Thread 那些事儿

    前言,才开始学安卓十几天,不料被线程挡住了前进的步伐,因为之前操作系统课程并没有认真听老师讲课,导致现在理解这些抽象的东西有些小困难.没关系,苦学之路,总会碰到坎坷,这里也给那些迷失在Android之 ...

  7. Java学习笔记17---成员方法的重载与重写

    重载是指,一个类中定义了一个成员方法后,通过修改参数个数.参数类型或参数顺序,重新实现该方法,则这两个方法互为对方的重载方法. 重写是指,子类重新实现父类的成员方法. 重载后的方法,与原方法相比: ( ...

  8. canda 常用命令

    1.获取版本 conda -V conda --version 2.获取帮助 conda -h conda --help 查看某一命令的帮助 conda install -h conda instal ...

  9. 小红帽安装centos的yum的一些坑!

    [root@localhost ~]# lsanaconda-ks.cfg yum-3.4.3-158.el7.centos.noarch.rpm yum-updateonboot-1.1.31-45 ...

  10. 【转载】法线贴图Nomal mapping 原理

    法线贴图多用在CG动画的渲染以及游戏画面的制作上,将具有高细节的模型通过映射烘焙出法线贴图,贴在低端模型的法线贴图通道上,使之拥有法线贴图的渲染效果,却可以大大降低渲染时需要的面数和计算内容,从而达到 ...