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模式可以用来把数据结构与处理分离开.通俗来说就是编写一个访问者类来访问数据结构中的元素,并把对各元素的处理交给访问者类.这样,当需要增加新的处理时,只需要编写新的访问者,然后让数据结构可 ...
随机推荐
- 关于对H264码流的PS的封装的相关代码实现
1.写在开始之前: 最近因为新工作要维护别人留下的GB模块代码,先熟悉了流程,然后也试着封装了下ps流,结果也能通过测试正常预览了,当然,其中开发读文档的头疼,预览花屏,卡帧的事情都有遇到,当时慢慢的 ...
- 9th
2017-2018-2 20179212<网络攻防实践>第9周作业 视频学习 KaliSecurity压力测试工具 压力测试通过确定一个系统的瓶颈或者不能接受的性能点,来获得系统能够提供的 ...
- NOIP2018爆炸记
又是一年\(NOIP\),可能是梦结束的地方? 之所以咕了这么久是得先确定自己不会退役,因为分太低了. 和去年一样在学校门前照了相,然后上车走了.高三回来考的只剩下\(p2oileen\)学姐了.新一 ...
- JS图表工具 ---- Highcharts
Highcharts 是一个用纯 JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是 web 应用程序添加有交互性的图表,并且免费提供给个人学习.个人网站和非商业用途使用. Hi ...
- ECMAScript中面向对象的程序设计思想总结
<JavaScript高级程序设计>Chapter6笔记 1.ECMAScript内部值属性:数据属性和访问器属性 1)数据属性 数据属性的4个特性: configurable:表示能否通 ...
- 问题13:如何在for语句中迭代多个可迭代的对象
from random import randint a1 = [randint(10, 50) for _ in range(5)] a2 = [randint(10, 50) for _ in r ...
- PG peered实验
标签(空格分隔): ceph,ceph实验,pg 1. 创建一个文件,并把该文件作为对象放到集群中: [root@node1 ~]# echo "this is test! " & ...
- Android Studio配置使用git
一.准备 如果没有安装git,那么先要到到Git官网下载git,然后按照提示一步一步安装即可,这个没有什么难度,不过要记得安装的目录. 二.Android Studio配置git File->S ...
- 【总结整理】javascript进阶学习(慕课网)
数组 数组是一个值的集合,每个值都有一个索引号,从0开始,每个索引都有一个相应的值,根据需要添加更多数值. 二维数组 二维数组 一维数组,我们看成一组盒子,每个盒子只能放一个内容. 一维数组的表示: ...
- zookeeper相关知识的总结:
一.分布式协调技术 在给大家介绍ZooKeeper之前先来给大家介绍一种技术——分布式协调技术.那么什么是分布式协调技术?那么我来告诉大家,其实分布式协调技术 主要用来解决分布式环境当中多个进程之间的 ...