23中设计模式之访问者visitor设计模式
“ 访问者设计模式学习心得分享”
适用于结构相对稳定的条目或者xxx对比时,其它相对稳定的层级组织架构使用该模式是OK滴
如条目中文件和文件夹的访问,男人和女人对同一件事情不同反应的对比
条目只分为文件和文件夹,人只分为男人和女人,这称之为结构稳定。
talk is cheap ,show me the code. 先看一张类图
jdk 使用到的访问者模式示例
java.nio.file.FileVisitor
java.nio.file.Files#walkFileTree
Path directory = Paths.get("target/perf-logs/");//作用:删除文件下的所有目录及文件,并将该文件夹也删掉if (Files.exists(directory)) {Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {Files.delete(file);return FileVisitResult.CONTINUE;}@Overridepublic FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {Files.delete(dir);return FileVisitResult.CONTINUE;}});
自定义MyElement 接口
package design_pattern.visitor.visitor2;
/*** 元素接口*/
public interface MyElement {void accept(Visitor visitor);
}
MyEntry 条目抽象类
package design_pattern.visitor.visitor2;import java.util.Iterator;/*** 条目抽象类*/
public abstract class MyEntry implements MyElement {public abstract String getName();public abstract int getSize();public abstract void printList(String prefix);public void printList() {printList("");}public MyEntry add(MyEntry entry) throws RuntimeException {throw new RuntimeException();}public Iterator iterator() throws RuntimeException {throw new RuntimeException();}public String toString() {return getName() + "<" + getSize() + ">";}
}
MyFile 自定义文件类
package design_pattern.visitor.visitor2;/*** 自定义文件类*/
public class MyFile extends MyEntry {private String name;private int size;public MyFile(String name, int size) {this.name = name;this.size = size;}@Overridepublic String getName() {return name;}@Overridepublic int getSize() {return size;}@Overridepublic void printList(String prefix) {System.out.println(prefix + "/" + this);}@Overridepublic void accept(Visitor visitor) {//重点代码visitor.visit(this);}}
MyDirectory 自定义目录类
package design_pattern.visitor.visitor2;import java.util.ArrayList;
import java.util.Iterator;/*** 自定义目录类*/
public class MyDirectory extends MyEntry {private String name;private ArrayList entrys = new ArrayList();public MyDirectory(String name) {this.name = name;}@Overridepublic String getName() {return name;}@Overridepublic int getSize() {int size = 0;Iterator it = entrys.iterator();while (it.hasNext()) {size += ((MyEntry) it.next()).getSize();}return size;}@Overridepublic MyEntry add(MyEntry entry) {entrys.add(entry);return this;}@Overridepublic Iterator iterator() {return entrys.iterator();}@Overridepublic void printList(String prefix) {System.out.println(prefix + "/" + this);//用for 遍历迭代器写法 快捷键itco,今晚刚发现滴for (Iterator iterator = entrys.iterator(); iterator.hasNext(); ) {MyEntry entry = (MyEntry) iterator.next();entry.printList(prefix + "/" + name);}}@Overridepublic void accept(Visitor visitor) {//重点代码visitor.visit(this);}}
Visitor 抽象访问者
package design_pattern.visitor.visitor2;/*** 抽象访问者*/
public abstract class Visitor {/*** 访问文件* @param myFile*/public abstract void visit(MyFile myFile);/*** 访问目录** @param directory*/public abstract void visit(MyDirectory directory);}
FileFoundVisitor 查找指定文件访问者
package design_pattern.visitor.visitor2;import java.util.ArrayList;
import java.util.Iterator;/*** 查找指定文件访问者*/
public class FileFoundVisitor extends Visitor {private String currentDir = "";private String suffix;private ArrayList files = new ArrayList();public FileFoundVisitor(String suffix) {this.suffix = suffix;}@Overridepublic void visit(MyFile myFile) {if (myFile.getName().endsWith(suffix)) {files.add(currentDir + "/" + myFile);}}public void visit(MyDirectory directory) {//先保存当前目录String saveDir = currentDir;//当前目录被改变currentDir += ("/" + directory.getName());Iterator it = directory.iterator();while (it.hasNext()) {MyEntry entry = (MyEntry) it.next();entry.accept(this);}//将当前目录改回来currentDir = saveDir;}public Iterator getFoundFiles() {return files.iterator();}}
ListVisitor 查找所有文件访问者
package design_pattern.visitor.visitor2;import java.util.Iterator;/*** 查找所有文件访问者*/
public class ListVisitor extends Visitor {String currentDir = "";public void visit(MyFile myFile) {System.out.println(currentDir + "/" + myFile);}public void visit(MyDirectory directory) {System.out.println(currentDir + "/" + directory);String saveDir = currentDir;currentDir += ("/" + directory.getName());Iterator it = directory.iterator();while (it.hasNext()) {MyEntry entry = (MyEntry) it.next();entry.accept(this);}currentDir = saveDir;}}
ObjectStructure 对象结构
package design_pattern.visitor.visitor2;import java.util.ArrayList;
import java.util.Iterator;/*** 对象结构*/
public class ObjectStructure extends ArrayList<MyElement> implements MyElement {@Overridepublic void accept(Visitor visitor) {//调用ArrayList的iterator方法for (Iterator<MyElement> iterator = this.iterator(); iterator.hasNext(); ) {MyElement element = iterator.next();element.accept(visitor);}}
}
Main 客户端
package design_pattern.visitor.visitor2;import java.util.Iterator;/*** 登场角色* >元素* >>条目* |--文件* |--文件夹* >访问者* |-- 查找指定文件访问者* |-- 查找所有文件访问者* >对象结构【其实内部就是个封装了ArrayList的容器,加了个accept方法】** <p>* 使用场景:当出现有组织结构、树形结构、多层级访问、问答场景 需要访问各个条目时,可以考虑用使用访问者设计模式* 相关模式:* 1.迭代器设计模式* 2.组合设计模式* <p>* 另外:* MyDirectory#printList(java.lang.String)方法 为我们提供了一种新的递归访问模型* 另外一种新的思路就是像本visitor模式一样使用【双重分发】* <pre>* public void accept(Visitor visitor) {* visitor.visit(this);* }* <pre/>* 他们是相反的关系,element接收visitor,visitor访问element,* 这种消息分发的方式被称为双重分发【double dispatch】** 为什么要弄得这么复复杂?* visitor模式的主要目的是将【处理】从数据结构中分离出来,* 【保存数据结构】和【以数据结构为基础】进行处理是两码事* 缺点:* visitor模式适用于元素基本不变的情况* 添加新的元素非常麻烦*/
public class Main {public static void main(String[] args) {//准备数据MyDirectory root = getData();//处理数据 可以替换为doData 、doData1、doData2doData3(root);}private static void doData3(MyDirectory root) {ObjectStructure objectStructure = new ObjectStructure();objectStructure.add(root);objectStructure.add(new MyFile("我是小孩也是王", 1));objectStructure.accept(new ListVisitor());}/*** 处理数据1:全部访问** @param root*/private static void doData(MyDirectory root) {root.accept(new ListVisitor());}/*** 处理数据2:访问数据并查找指定格式的文文件** @param root*/private static void doData2(MyDirectory root) {FileFoundVisitor visitor = new FileFoundVisitor(".psd");root.accept(visitor);//打印获取到的指定文件Iterator it = visitor.getFoundFiles();while (it.hasNext()) {System.out.println(it.next());}}private static MyDirectory getData() {MyDirectory root = new MyDirectory("根目录");MyDirectory life = new MyDirectory("我的生活");MyFile eat = new MyFile("吃火锅.txt", 100);MyFile sleep = new MyFile("睡觉.html", 100);MyFile study = new MyFile("学习.txt", 100);life.add(eat);life.add(sleep);life.add(study);MyDirectory work = new MyDirectory("我的工作");MyFile write = new MyFile("写博客.doc", 200);MyFile paper = new MyFile("写论文.html", 200);MyFile homework = new MyFile("写家庭作业.docx", 200);work.add(write);work.add(paper);work.add(homework);MyDirectory relax = new MyDirectory("我的休闲");MyFile music = new MyFile("听听音乐.js", 200);MyFile walk = new MyFile("出去转转.psd", 200);relax.add(music);relax.add(walk);MyDirectory read = new MyDirectory("我的阅读");MyFile book = new MyFile("学习书籍.psd", 200);MyFile novel = new MyFile("娱乐小说.txt", 200);read.add(book);read.add(novel);root.add(life);root.add(work);root.add(relax);root.add(read);return root;}}
总结
登场角色
元素 >>条目 |–文件 |–文件夹
访问者 |-- 查找指定文件访问者 |-- 查找所有文件访问者
对象结构【其实内部就是个封装了ArrayList的容器,加了个accept方法】
使用场景:当出现有组织结构、树形结构、多层级访问、问答场景
需要访问各个条目时,可以考虑用使用访问者设计模式
相关模式:
1.迭代器设计模式
2.组合设计模式
另外:MyDirectory#printList(java.lang.String)方法 为我们提供了一种新的递归访问模型 另外一种新的思路就是像本visitor模式一样使用【双重分发】
public void accept(Visitor visitor) {
visitor.visit(this);
}
他们是相反的关系,element接收visitor,visitor访问element,
这种消息分发的方式被称为双重分发【double dispatch】 为什么要弄得这么复复杂?
visitor模式的主要目的是将【处理】从数据结构中分离出来,
【保存数据结构】和【以数据结构为基础】进行处理是两码事
缺点:
visitor模式适用于元素基本不变的情况
添加新的元素非常麻烦
写在最后
总结:本片文章我们主要描述了什么是访问者visitor设计模式,以及使用场景。以及本设计模式相关联的模式:如迭代器设计模式和组合设计模式
,这些都是相互关联的,设计模式是一种套路、是一种模板、是一种经验,是一种角色扮演,每个模式都有其登场角色,我们自己在设计和编程时,要思考一下学习过的设计模,是否适用于当前场景。
正所谓点动成线,线动成面,面动成一片
你现在多努力一份,以后老婆就多漂亮一分,加油吧,少年!!!
23中设计模式之访问者visitor设计模式相关推荐
- java中23中设计模式详解
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- 三句话巧记23中设计模式
大家都知道23中设计模式,其中又可以分成三类,创建型模式,结构型模式,行为型模式.但是总是在实际应用中忘记了,当具体看到一些代码的时候也想不起来具体对应的是哪种设计模式,对经常重构的代码人员来说是一个 ...
- Python如何实现单例模式?其他23中设计模式python如何实现?
单例模式主要有四种方法:new.共享属性.装饰器.import. # __ new__方法:class Singleton(object):def __new__(cls, *args, **kw): ...
- 软件设计模式(23中设计模式)
目录 1. 软件架构设计模式 2. 设计模式特点 3. 设计模式分类 3.1 面向对象设计原则 3.2 5种创建型模式 3.3 7种结构性模式 3.4 11种行为性模式 参考 1. 软件架构设计模式 ...
- 史上最详细的23中设计模式解析,一个不落,理论搭配简单案例,更好理解哦
目录 一.软件设计模式的产生背景 二.软件设计模式的概念与意义 1. 软件设计模式的概念 2. 学习设计模式的意义 三.23 种设计模式的分类和功能 1. 根据目的来分 2. 根据作用范围来分 3. ...
- 追MM和23中设计模式(来自网络)
设计模式做为程序员的"内功心法",越来越受到重视.这是一篇通俗版23种设计模式,用实际生活做比喻,让你很快就能理解其中的深意. 1.FACTORY―追MM少不了请吃饭了,麦当劳的鸡 ...
- Java常见的23中设计模式
工厂模式, 工厂方法模式,单例模式, 外观(Facade)模式, 观察者(Observer)模式,桥接(Bridge)模式都是比较常用的,不同的项目有不同的设计方向,可以参考的设计模式也不尽相同,没有 ...
- java中的23中设计模式
1.工厂模式:客户类和工厂类分开.消费者任何时候需要某种产品,只需向工厂请求即可.消费者无须修改就可以接纳新产品.缺点是当产品修改时,工厂类也要做相应的修改.如:如何创建及如何向客户端提供. 2. ...
- 【GOF】23中设计模式深析
2019独角兽企业重金招聘Python工程师标准>>> ###对象创建 原型模式.工厂模式.抽象工厂模式.生成器.单例模式 ###接口适配 适配器模式.桥接.外观模式.迭代器 ### ...
最新文章
- memcpy()函数
- Elasticsearch之集群脑裂
- 独家 | 一文读懂Apache Kudu
- 类型重定义 头文件预编译设置
- AI Frontiers | 微软首席 AI 科学家邓力演讲:口语对话系统的分类及三代演变
- Boost::context模块callcc的jump_void测试程序
- 关于jedis2.4以上版本的连接池配置,及工具类
- Facebook 约十亿美元收购脑机技术公司,助攻AR研发;苹果宣布新款 Mac Pro 在美国生产;谷歌称已实现量子霸权…...
- 作者:季统凯,男,博士,中国科学院云计算中心主任、研究员,国云科技股份有限公司董事长,中国云计算专家委员会委员。...
- 如何更新Node.js?
- Maven项目中父子项目互相找不到的解决方法
- 用java 解密pdf_Java 加密、解密PDF文档(示例代码)
- 2021年物联网设备CVE天梯榜
- 快速复现利用Log4j漏洞启动windows计算器
- 动态背景下的运动目标检测
- Java笔试面试题三(编程算法)
- 怎么批量下载Onedrive分享文件_怎么用PS弄字幕文件 PS批量生成字幕制作教程
- 无扩展,不 Chrome
- 2038:最大数位置(题目来源于信息奥赛一本通官网)
- 手把手教大家如何给域名申请免费SSL证书