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模式(访问者设计模式)的更多相关文章

  1. 设计模式之美:Visitor(访问者)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Visitor 模式结构样式代码. 实现方式(二):使用 Visitor 模式解构设计. 实现方式(三):使用 Acyclic ...

  2. 访问者模式 Visitor 行为型 设计模式(二十七)

    访问者模式 Visitor    <侠客行>是当代作家金庸创作的长篇武侠小说,新版电视剧<侠客行>中,开篇有一段独白:  “茫茫海外,传说有座侠客岛,岛上赏善罚恶二使,每隔十年 ...

  3. 设计模式C++描述----22.访问者(Visitor)模式

    一. 访问者模式 定义:表示一个作用于某对象结构中的各元素的操作.它你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 结构如下: 二. 举例 假设有一项科学实验,是用来对比两种种子在不同环 ...

  4. 设计模式之visitor模式,人人能懂的有趣实例

    设计模式,现在在网上随便搜都一大堆,为什么我还要写"设计模式"的章节呢? 两个原因: 1.本人觉得这是一个有趣的设计模式使用实例,所以记下来: 2.看着设计模式很牛逼,却不知道怎么 ...

  5. 访问者模式(Visitor模式)

    模式的定义与特点 访问者(Visitor)模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提 ...

  6. 设计模式:基于线程池的并发Visitor模式

    1.前言 第二篇设计模式的文章我们谈谈Visitor模式. 当然,不是简单的列个的demo,我们以电商网站中的购物车功能为背景,使用线程池实现并发的Visitor模式,并聊聊其中的几个关键点. 一,基 ...

  7. 设计模式之Visitor(访问者)(转)

    Visitor定义 作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作. 在Java中,Visitor模式实际上是分离了collection结构中的 ...

  8. 设计模式之——visitor模式

    visitor模式,又叫访问者模式,把结构和数据分开,编写一个访问者,去访问数据结构中的元素,然后把对各元素的处理全部交给访问者类.这样,当需要增加新的处理时候,只需要编写新的 访问者类,让数据结构可 ...

  9. 设计模式(十三)Visitor模式

    Visitor模式可以用来把数据结构与处理分离开.通俗来说就是编写一个访问者类来访问数据结构中的元素,并把对各元素的处理交给访问者类.这样,当需要增加新的处理时,只需要编写新的访问者,然后让数据结构可 ...

随机推荐

  1. 【C/C++】scanf,printf 函数

    摘自http://www.cplusplus.com 1. scanf 函数 int scanf ( const char * format, ... ); Parameters format C s ...

  2. vue-router路由嵌套的使用

    vue-router路由嵌套的使用,以及子路由中设置默认路由: 项目结构: 在/src/App.vue文件中: <template> <div id="app"& ...

  3. Unity Webplayer installation error- Unity Webplayer update finished, but installed..

    https://forum.unity3d.com/threads/unity-webplayer-installation-error-unity-webplayer-update-finished ...

  4. 51nod 1250 排列与交换——dp

    题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1250 仔细思考dp. 第一问,考虑已知 i-1 个数有多少种方案. ...

  5. poj 2187 Beauty Contest —— 旋转卡壳

    题目:http://poj.org/problem?id=2187 学习资料:https://blog.csdn.net/wang_heng199/article/details/74477738 h ...

  6. GSM与GPRS区别介绍

    1.    GSM是全球移动通讯系统(Global System for Mobile Communications)的简称 2.    GPRS是通用分组无线业务(General Packet Ra ...

  7. MyEclipse、Eclipse SVN插件的帐号、密码修改

    问题描述: Eclipse的SVN插件Subclipse做得很好,在svn操作方面提供了很强大丰富的功能.但到目前为止,该插件对svn用户的概念极为淡薄,不但不能方便地切换用户,而且一旦用户的帐号.密 ...

  8. 自定义echart tooltip格式

    formatter: function (tipData) { return tipData[0].name + '</br>' + '<span style="displ ...

  9. CSS样式基础:

    CSS:外部文件导入  <link rel="stylesheet" type="text/css" href="./style.css&quo ...

  10. 22、IDP-ASE

    IDPASE https://github.com/bdeonovic/IDPASE.jl Prepare necessary input files (1)FASTQ file of your hy ...