Visitor模式(访问者设计模式)
Visitor ?
在Visitor模式中,数据结构与处理被分离开来。我们编写一个表示“访问者”的类来访问数据结构中的元素,
并把对各元素的处理交给访问者类。这样,当需要增加新的处理时,我们只需要编写新的访问者,然后让
数据结构可以接受访问者的访问即可。 **概括: 数据结构与处理彼此分开,当需要实现新数据访问方式的时候,实现Visitor就行了,(缺点:如果增加元素的访问那会非常麻烦)
理清职责
作用:这里用到Composition设计模式的那个文件和文件夹的例子作为访问者要访问的数据结构。
地址:https://www.cnblogs.com/dgwblog/p/9840291.html
名字================>>>> 说明
| Visitor || 表示访问者的抽象类,它访问文件和文件夹
|ELement || 表示数据结构的接口,它接受访问者的访问
|ListVisitor|visitor || 类的子类,显示文件和文件夹一览
|Fi1e类和Directory || 类的父类,它是抽象类
|Entry(实现了Element接口)
|File || 表示文件的类
|Directory || 表示文件夹的类
|FileTreatementException || 表示向文件中add时发生的异常的类
|Main ||测试程序行为的类简单说明:
Visitor与ELement 作用在你把代码阅读以后会发现真的是非常简单:如果说Composite中容器与内容一致性,这里是还是将内容一致性维持着,但是将
那我们需要的数据结构的那部门的实现一套接口访问者提取出来,实现的真正的访问。
rootdir.acctep(new ListVisitor());
/*ListVisitor visitor = new ListVisitor();
visitor.visit(rootdir);*/
accept(接受)方法的调用方式如下。
element.accept(visitor);
而visit(访问)方法的调用方式如下。
visitor.visit (element);
把上面这两者情况,我们叫做消息的双重分发
UML

时序图:

- 对于Directory类的实例和Fi1e类的实例,我们调用了它们的accept方法
- 对于每一个Directory类的实例和File类的实例,我们只调用了一次它们的accept方法
- 对于ListvVisitor的实例,我们调用了它的visit(Directory)和visit(File)方法
- 处理visit(Directory)和visit(File)的是同一个ListVisitor的实例
Code
- Entry :
public abstract class Entry implements Element {
// 这里实现的Element的目的 是便于在后面的Concreate类中Visitor进行访问
/**
* 1. 文件名
* 2. 文件大小
* @return
*/
public abstract String getName();
public abstract int getSize();
/**
* Directory 增加条目
* File 不能增加条目
*/
public Entry add(Entry entry)throws FileTreatementException {
throw new FileTreatementException();
}
/**
* 增加数据的遍历方法itorator
* @return
*/
public Iterator iterator() throws FileTreatementException{
throw new FileTreatementException();
}
@Override
public String toString() {
return getName()+"("+getSize()+")";
}
}
- Element、ListVisitor 、Visitor
public abstract class Visitor {
/**
* 作用: 这里的方法的重载数量决定你数据结构中数据的参数
* 这里我们需要访问 File Directory
*/
abstract void visit(File file);
abstract void visit(Directory directory);
}
public interface Element {
void acctep(Visitor visitor);
}
public class ListVisitor extends Visitor {
private String currentDir="";
@Override
void visit(File file) {
System.out.println(currentDir+"/"+file);
}
/**
* 实现递归访问结构
*/
@Override
void visit(Directory directory) {
System.out.println(currentDir+"/"+directory);
String saveDir=currentDir;
currentDir=currentDir+"/"+directory.getName();
try {
Iterator it = directory.iterator();
while(it.hasNext()){
Entry o = (Entry) it.next();
o.acctep(this);
}
currentDir =saveDir;
} catch (FileTreatementException e) {
e.printStackTrace();
}
}
}
- Directory,File
public class File extends Entry {
private String name;
private int size;
public File(String name, int size) {
this.name = name;
this.size = size;
}
@Override
public String getName() {
return name;
}
@Override
public int getSize() {
return size;
}
@Override
public void acctep(Visitor visitor) {
visitor.visit(this);
}
}
public class Directory extends Entry {
private String name;
private List<Entry> directory=new ArrayList<>();
public Directory(String name) {
this.name = name;
}
@Override
public Entry add(Entry entry) throws FileTreatementException {
directory.add(entry);
return this;
}
@Override
public String getName() {
return name;
}
/**
* getSize() | printList(String prefix)
*
* 都会递归去遍历下面可能存在的 目录或者文件的子项
*/
@Override
public int getSize() {
int size=0;
Iterator<Entry> it = directory.iterator();
while (it.hasNext()){
// 这里的Entry 可能是目录 也可能是文件
Entry next = it.next();
size+=next.getSize();
}
return size;
}
@Override
public Iterator iterator() throws FileTreatementException {
return directory.iterator();
}
@Override
public void acctep(Visitor visitor) {
visitor.visit(this);
}
}
- FileTreatementException ,
public class FileTreatementException extends Exception {
public FileTreatementException() {
}
public FileTreatementException(String message) {
super(message);
}
}
- MainT
public class MainT {
public static void main(String[] args) throws FileTreatementException{
System.out.println("start +++++++++++");
Directory rootdir=new Directory("root");
Directory bindir = new Directory("bin");
Directory tempdir = new Directory("temp");
Directory userdir = new Directory("user");
rootdir.add(bindir);
rootdir.add(tempdir);
rootdir.add(userdir);
bindir.add(new File("vi",1000));
bindir.add(new File("notepaid",15000));
rootdir.acctep(new ListVisitor());
/*ListVisitor visitor = new ListVisitor();
visitor.visit(rootdir);*/
}
}
Visitor模式(访问者设计模式)的更多相关文章
- 设计模式之美:Visitor(访问者)
索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Visitor 模式结构样式代码. 实现方式(二):使用 Visitor 模式解构设计. 实现方式(三):使用 Acyclic ...
- 访问者模式 Visitor 行为型 设计模式(二十七)
访问者模式 Visitor <侠客行>是当代作家金庸创作的长篇武侠小说,新版电视剧<侠客行>中,开篇有一段独白: “茫茫海外,传说有座侠客岛,岛上赏善罚恶二使,每隔十年 ...
- 设计模式C++描述----22.访问者(Visitor)模式
一. 访问者模式 定义:表示一个作用于某对象结构中的各元素的操作.它你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 结构如下: 二. 举例 假设有一项科学实验,是用来对比两种种子在不同环 ...
- 设计模式之visitor模式,人人能懂的有趣实例
设计模式,现在在网上随便搜都一大堆,为什么我还要写"设计模式"的章节呢? 两个原因: 1.本人觉得这是一个有趣的设计模式使用实例,所以记下来: 2.看着设计模式很牛逼,却不知道怎么 ...
- 访问者模式(Visitor模式)
模式的定义与特点 访问者(Visitor)模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提 ...
- 设计模式:基于线程池的并发Visitor模式
1.前言 第二篇设计模式的文章我们谈谈Visitor模式. 当然,不是简单的列个的demo,我们以电商网站中的购物车功能为背景,使用线程池实现并发的Visitor模式,并聊聊其中的几个关键点. 一,基 ...
- 设计模式之Visitor(访问者)(转)
Visitor定义 作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作. 在Java中,Visitor模式实际上是分离了collection结构中的 ...
- 设计模式之——visitor模式
visitor模式,又叫访问者模式,把结构和数据分开,编写一个访问者,去访问数据结构中的元素,然后把对各元素的处理全部交给访问者类.这样,当需要增加新的处理时候,只需要编写新的 访问者类,让数据结构可 ...
- 设计模式(十三)Visitor模式
Visitor模式可以用来把数据结构与处理分离开.通俗来说就是编写一个访问者类来访问数据结构中的元素,并把对各元素的处理交给访问者类.这样,当需要增加新的处理时,只需要编写新的访问者,然后让数据结构可 ...
随机推荐
- freeMarker(十二)——模板语言补充知识
学习笔记,选自freeMarker中文文档,译自 Email: ddekany at users.sourceforge.net 1.特殊变量参考 特殊变量是由FreeMarker引擎自己定义的变量. ...
- ONVIF Device Manager v2.2.146
对接ONVIF使用软件,用于对接支持onvif协议的IPC厂家设置 http://download.csdn.net/detail/li_dabo/9761415
- HDU5446 Unknown Treasure(组合数膜合数-->Lucas+中国剩余定理)
>On the way to the next secret treasure hiding place, the mathematician discovered a cave unknown ...
- bzoj 2001: City 城市建设 cdq
题目 PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁.Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费.Louis希望建造最少的道路使得国内所有 ...
- bzoj 3730 震波 —— 动态点分治+树状数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3730 建点分树,每个点记两个树状数组,存它作为重心管辖的范围内,所有点到它的距离情况和到它在 ...
- centos 6 rsync+inotify 实时同步
主机名.ip: server 172.31.82.184 client 172.31.82.185 需求: 1.server端 ”/data/server“ 做为client端 “/data/cli ...
- 计算MySQL的内存峰值公式 (转)
-- 计算MySQL的内存峰值公式,计算所有的连接满了的情况下: select (@@key_buffer_size + @@query_cache_size + @@tmp_table_size ...
- IIS应用池保持激活工具开发
之前的 开源一个定时任务调度器 webscheduler 中涉及的定时调用应用已经开始在正式环境中启用,发布到IIS下进行测试,发现一旦应用长时间没有访问(大约半个多小时)就会引发 Applicati ...
- SpringMvc之参数绑定注解详解之四
简介: @RequestBody 作用: i) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对 ...
- 又来一波!Android精品源码分享
今天又汇总了几个不错的源码给大家!希望能帮到需要的小伙伴~话不多少,直接上源码! 1.Android精品源码:拖动条控件实现源码 此次分享的源码是一个不错的Android控件,建议大家可以细致的看下. ...