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模式可以用来把数据结构与处理分离开.通俗来说就是编写一个访问者类来访问数据结构中的元素,并把对各元素的处理交给访问者类.这样,当需要增加新的处理时,只需要编写新的访问者,然后让数据结构可 ...
随机推荐
- 七牛 python
Python SDK使用指南 上传策略 变量 对象存储 API 参考手册 多媒体数据处理 API 参考手册
- BZOJ5324 JXOI2018 守卫
传送门 这是我见过的为数不多的良心九怜题之一 题目大意 给定一段$n$个点构成的折线,第$i$个折点的坐标是$(i,h_i)$,你可以在$i$点放置一个视野,定义$i$能看到$j$当且仅当$i$处有视 ...
- 发布django 程序
1.配置需求环境 pip freeze > requirements.txt 在开发环境将工程依赖的包导出. pip install virtualenv pip install virtual ...
- powermock, 强力模拟
1. powermock是基于mockito或者easymock,TestNG之上的mock: 2. 提供了对于静态函数,私有函数的mock 3. 下载地址:https://github.com/po ...
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
几大最短路径算法比较 转自:http://blog.csdn.net/v_july_v/article/details/6181485 几个最短路径算法的比较: Floyd 求多 ...
- 【转】mysql查询当天所有数据sql语句
mysql查询当天的所有信息: select * from test where year(regdate)=year(now()) and month(regdate)=month(now()) a ...
- uboot 命令使用教程(uboot参数设置)
1. Printenv 打印环境变量. uboot> printenv baudrate=115200 ipaddr=192.168.0.111 ethaddr=32:34:46:78:9A:D ...
- 对象流demo1----
对象流demo1: package com.etc.test; import java.io.BufferedInputStream; import java.io.BufferedOutputStr ...
- PhpStorm选中相同文字高亮
1.Setting(设置)->plugins->Browse Repositories 输入BrowseWordAtCaret 搜索,安装,然后重启: 2.Setting(设置) -> ...
- 常见的CSS和HTML面试题
1. 常用那几种浏览器测试?有哪些内核(Layout Engine)? 浏览器:IE,Chrome,FireFox,Safari,Opera. 内核:Trident,Gecko,Presto,Webk ...