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模式可以用来把数据结构与处理分离开.通俗来说就是编写一个访问者类来访问数据结构中的元素,并把对各元素的处理交给访问者类.这样,当需要增加新的处理时,只需要编写新的访问者,然后让数据结构可 ...
随机推荐
- 在YUV图像上根据背景色实现OSD反色
所谓的OSD其实就是在视频图像上叠加一些字符信息,比如时间,地点,通道号等, 在图像上叠加OSD通常有两种方式: 一种是在前端嵌入式设备上,在图像数据上叠加OSD, 这样客户端这边只需解码显示数据即可 ...
- bzoj 1006: 神奇的国度 MCS
题目大意: 弦图的最小染色. 题解: 裸题. #include <vector> #include <cstdio> #include <cstring> #inc ...
- HEOI2017题解
Day 1 : T1 : 期末考试 很水的一道题,但是自己搞了大半天过不了大样例. 最后还A了... 主要思想就是枚举最后一个完成的任务的时间 然后对两部分的代价分类讨论统计一下. (考试代码,略丑) ...
- BZOJ2809:[APIO2012]dispatching
浅谈左偏树:https://www.cnblogs.com/AKMer/p/10246635.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php? ...
- 【转】 Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner
目录(?)[-] GridView Spinner GridView GridView是网格状布局,如图所示.在了解ListView后,很容易了解GridView.下面是例子的XML文件. <? ...
- 多校联合训练&hdu5791 Two
hdu5791 dp[i][j]表示的是序列A前i个数字和序列B前j个数字的公共子序列的总个数,那么的dp公式就可以这么表示 理解一下此公式若最尾部的a[i]和b[j]相等的话,那么单独的a[i]和b ...
- cmake opencv,dlib 编译静态库 1
无论windows,linux 所有的库 ,dlib,opencv 通过cmake-gui 设置好静态库, 动态库,和其他各个选项 Tips: cmake 优先级用cmake-gui,因为命令太多,容 ...
- 用paramiko写堡垒机
paramiko paramiko模块,基于SSH用于连接远程服务器并执行相关操作. 基本用法 SSHClient 基于用户名密码连接: 基础用法: import paramiko # 创建SSH对象 ...
- python 基础 操作文件和目录
获得当前目录路径 :os.getcwd() 返回指定目录下的所有文件和目录名:os.listdir() 删除一个文件:os.remove(filename) 删除多个空目录 :os.removefir ...
- 安装Ruby On Rails时运行“gem install rails”没有反应怎么办?
这两天在我的mac机上安装Ruby On Rails,感觉很爽,似乎在使用一个Windows和Linux的结合体,要界面有界面,要命令行有命令行. 不过安装Ruby On Rails的过程中遇到一个问 ...