浅谈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脚本编程及效率优化 小论文,大家多批评指导:) ...
随机推荐
- go get超时解决办法
go get gopkg.in/yaml.v2超时,发现被墙了,解决办法如下: 1.安装golang.org/x/net $ mkdir -p $GOPATH/src/golang.org/x/ $ ...
- php动态画图
index.php <?php $width=800; $height=600; //绘图技术 基本步骤 前提:在php.ini文件中启用gd库 //创建画布 默认背景是黑色的 $img=ima ...
- PHP成随机字符串
生成随机字符串 /** * 随机字符串 * @param int $len * @return string */ function randomStr($len = 32) { $chars = & ...
- MySql编码、卸载、启动问题
一.启动问题 计算机------管理------服务------找到MySql------右键------启动或停止 问题:打开Mysql,点击 MySQL Command Line Client,输 ...
- python简介,数据类型,input,if语句
1. python的起源 python的创始人为吉多·范罗苏姆(龟叔Guido van Rossum),1989年的圣诞节期间,龟叔为了在阿姆斯特丹打发时间 决心开发一个新的脚本程序解释器,作为A ...
- python学习之字符串转换
配置环境:python 3.6 python编辑器:pycharm 代码如下: #!/usr/bin/env python #-*- coding: utf-8 -*- def strCase() ...
- Fruits【水果】
Fruits Many of us love July because it's the month when nature's berries and stone fruits are in abu ...
- python向多个邮箱发邮件--注意接收是垃圾邮件
群发邮件注意:三处标红的地方 # -*- coding: UTF-8 -*- import smtplib from email.mime.text import MIMEText from emai ...
- JS中调用android和ios系统手机打开相机并可选择相册功能
编写不易,如有转载,请声明出处: 梦回河口:http://blog.csdn.net/zxc514257857/article/details/57626154 实现android手机打开相机选择相册 ...
- NC-瑞士军刀NetCat
NC——Telnet/Banner 连接之后可以命令互动,比如POP3\SMTP\HTTP等协议命令 root@kali:/# nc -v pop3..com //-v详细显示 DNS fwd/rev ...