设计模式学习笔记——访问者(Visitor)模式
设计模式学习笔记——访问者(Visitor)模式
@(设计模式)[设计模式, 访问者模式, visitor]
- 设计模式学习笔记访问者Visitor模式
- 基本介绍
- 访问者案例
- 类图
- 实现代码
- Visitor抽象类
- ListVisitor类
- Element接口
- Entry抽象类
- File类
- Directory类
- FileTreatmentException类
- 测试类
- 运行结果
- 访问者模式中的角色
- Visitor访问者
- ConcreteVisitor具体的访问者
- Element元素
- ConcreteElement
- ObjectStructure对象结构
- 类图
基本介绍
访问者模式主要的作用是对对象中元素进行操作。
使用访问者模式,在更改对元素的操作时,不需要更改类的定义。
访问者案例
类图
实现代码
Visitor抽象类
package com.pc.visitor.example;/*** 访问者抽象类* Created by Switch on 2017-02-22.*/
public abstract class Visitor {/*** 访问文件** @param file 文件对象*/public abstract void visit(File file);/*** 访问文件夹** @param directory 文件夹对象*/public abstract void visit(Directory directory);
}
ListVisitor类
package com.pc.visitor.example;import java.util.Iterator;/*** 列表访问类* Created by Switch on 2017-02-22.*/
public class ListVisitor extends Visitor {/*** 当前访问的文件夹的名字*/private String currentDir = "";@Overridepublic void visit(File file) {System.out.println(this.currentDir + "/" + file);}@Overridepublic void visit(Directory directory) {System.out.println(currentDir + "/" + directory);// 递归调用,回溯法String saveDir = this.currentDir;this.currentDir = this.currentDir + "/" + directory.getName();Iterator<Entry> iterator = directory.iterator();while (iterator.hasNext()) {Entry entry = iterator.next();entry.accept(this);}this.currentDir = saveDir;}
}
Element接口
package com.pc.visitor.example;/*** 元素接口(代表可以接受访问)* Created by Switch on 2017-02-22.*/
public interface Element {/*** 接受访问者对象访问** @param visitor 访问者对象*/void accept(Visitor visitor);
}
Entry抽象类
package com.pc.visitor.example;/*** 条目抽象类* Created by Switch on 2017-02-21.*/
public abstract class Entry implements Element {/*** 获取名字** @return 名字*/public abstract String getName();/*** 获取占用空间** @return 占用空间*/public abstract int getSize();/*** 添加** @param entry 条目对象* @return 返回文件夹对象* @throws FileTreatmentException 文件处理异常*/public Entry add(Entry entry) throws FileTreatmentException {throw new FileTreatmentException("只有文件夹才能添加条目!");}/*** 使用默认前缀,显示目录条目*/public void printList() {printList("");}/*** 指定前缀,显示目录条目** @param prefix 前缀*/protected abstract void printList(String prefix);@Overridepublic String toString() {return this.getName() + " (" + this.getSize() + ")";}
}
File类
package com.pc.visitor.example;/*** 文件类* Created by Switch on 2017-02-21.*/
public class File extends Entry {/*** 文件名*/private String name;/*** 文件占用空间*/private int size;/*** 构造方法,传入文件名和文件占用空间** @param name 文件名* @param size 文件占用空间*/public File(String name, int size) {this.name = name;this.size = size;}@Overridepublic String getName() {return this.name;}@Overridepublic int getSize() {return this.size;}@Overrideprotected void printList(String prefix) {System.out.println(prefix + "/" + this);}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}
Directory类
package com.pc.visitor.example;import com.pc.abstractfactory.example.factory.Item;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;/*** 文件夹类* Created by Switch on 2017-02-21.*/
public class Directory extends Entry {/*** 文件夹名*/private String name;/*** 文件夹中的条目集合*/private List<Entry> entries = new ArrayList<>();/*** 构造方法,传入文件夹名** @param name 文件夹名*/public Directory(String name) {this.name = name;}@Overridepublic String getName() {return this.name;}@Overridepublic int getSize() {int size = 0;for (Entry entry : entries) {size += entry.getSize();}return size;}@Overridepublic Entry add(Entry entry) {this.entries.add(entry);return this;}@Overrideprotected void printList(String prefix) {System.out.println(prefix + "/" + this);for (Entry entry : entries) {// 打印文件夹下的文件列表,以文件夹前缀,文件名作为前缀entry.printList(prefix + "/" + this.name);}}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}/*** 获取迭代器** @return 迭代器*/public Iterator<Entry> iterator() {return this.entries.iterator();}
}
FileTreatmentException类
package com.pc.visitor.example;/*** 文件处理异常* Created by Switch on 2017-02-21.*/
public class FileTreatmentException extends RuntimeException {public FileTreatmentException() {}public FileTreatmentException(String message) {super(message);}
}
测试类
package com.pc.visitor.example.test;import com.pc.visitor.example.Directory;
import com.pc.visitor.example.File;
import com.pc.visitor.example.FileTreatmentException;
import com.pc.visitor.example.ListVisitor;
import org.junit.Test;/*** Visitor Tester.** @author Switch* @version 1.0*/
public class VisitorTest {/*** 测试访问者模式*/@Testpublic void testVisitor() {try {System.out.println("添加文件和文件夹:");System.out.println("Making root entries...");Directory rootDir = new Directory("root");Directory binDir = new Directory("bin");Directory usrDir = new Directory("usr");rootDir.add(binDir);rootDir.add(usrDir);binDir.add(new File("java", 5000));binDir.add(new File("javac", 10000));rootDir.accept(new ListVisitor());System.out.println();System.out.println("接着添加文件和文件夹:");System.out.println("Making user entries...");Directory switchvov = new Directory("switchvov");Directory kity = new Directory("kity");Directory tom = new Directory("tom");Directory bob = new Directory("bob");usrDir.add(switchvov);usrDir.add(kity);usrDir.add(bob);switchvov.add(new File("readme.txt", 1000));switchvov.add(new File("hello.txt", 400));kity.add(new File("find.sh", 5000));rootDir.accept(new ListVisitor());} catch (FileTreatmentException e) {e.printStackTrace();}}
}
运行结果
添加文件和文件夹:
Making root entries...
/root (15000)
/root/bin (15000)
/root/bin/java (5000)
/root/bin/javac (10000)
/root/usr (0)接着添加文件和文件夹:
Making user entries...
/root (21400)
/root/bin (15000)
/root/bin/java (5000)
/root/bin/javac (10000)
/root/usr (6400)
/root/usr/switchvov (1400)
/root/usr/switchvov/readme.txt (1000)
/root/usr/switchvov/hello.txt (400)
/root/usr/kity (5000)
/root/usr/kity/find.sh (5000)
/root/usr/bob (0)
访问者模式中的角色
Visitor(访问者)
Visitor
角色负责对数据结构中每个具体的元素(ConcreteElement
角色)声明一个用于访问xxxxx
的visit(XXXXX)
方法。visit(XXXXX)
是用于处理xxxxx
的方法,负责实现该方法的是ConcreteVisitor
角色。在案例中,由Visitor
类扮演此角色。
ConcreteVisitor(具体的访问者)
ConcreteVisitor
角色负责实现Visitor
角色所定义的接口(API
)。它要实现所有的visit(XXXXX)
方法,即实现如何处理每个ConcreteElement
角色。在案例中,由ListVisitor
类扮演此角色。如同在ListVisitor
中, currentdir
字段的值不断发生变化一样,随着visit(XXXXX)
处理的进行,ConcreteVisitor
角色的内部状态也会不断地发生变化。
Element(元素)
Element
角色表示Visitor
角色的访问对象。它声明了接受访问者的accept
方法。accept
方法接收到的参数是Visitor
角色。在案例中,由Element
接口扮演此角色。
ConcreteElement
ConcreteElement
角色负责实现Element
角色所定义的接口(API
)。在案例中,由File
类和Directory
类扮演此角色。
ObjectStructure(对象结构)
ObjectStructur
角色负责处理Element
角色的集合。ConcreteVisitor
角色为每个Element
角色都准备了处理方法。在案例中,由Directory
类扮演此角色( 一人分饰两角)。为了让ConcreteVisitor
角色可以遍历处理每个Element
角色,在案例中,我们在Directory
类中实现了iterator
方法。
类图
GitHub:DesignPatternStudy
——————参考《图解设计模式》
设计模式学习笔记——访问者(Visitor)模式相关推荐
- 设计模式学习笔记--访问者(Visitor)模式
写在模式学习之前 什么是设计模式:在我们进行程序设计时,逐渐形成了一些典型问题和问题的解决方案,这就是软件模式:每一个模式描述了一个在我们程序设计中经常发生的问题,以及该问题的解决方案:当我们碰到模式 ...
- 设计模式学习笔记——解释器(Interpreter)模式
设计模式学习笔记--解释器(Interpreter)模式 @(设计模式)[设计模式, 解释器模式, Interpreter] 设计模式学习笔记解释器Interpreter模式 基本介绍 解释器案例 类 ...
- 设计模式学习笔记——命令(Command)模式
设计模式学习笔记--命令(Command)模式 @(设计模式)[设计模式, 命令模式, command] 设计模式学习笔记命令Command模式 基本介绍 命令案例 类图 实现代码 Command接口 ...
- 设计模式学习笔记——代理(Proxy)模式
设计模式学习笔记--代理(Proxy)模式 @(设计模式)[设计模式, 代理模式, proxy] 设计模式学习笔记代理Proxy模式 基本介绍 代理案例 类图 实现代码 Printable接口 Pri ...
- 设计模式学习笔记——状态(State)模式框架
设计模式学习笔记--状态(State)模式框架 @(设计模式)[设计模式, 状态模式, State] 设计模式学习笔记状态State模式框架 基本介绍 状态案例 类图 实现代码 State接口 Day ...
- 设计模式学习笔记——备忘录(Memento)模式
设计模式学习笔记--备忘录(Memento)模式 @(设计模式)[设计模式, 备忘录模式, memento] 设计模式学习笔记备忘录Memento模式 基本介绍 备忘录案例 类图 实现代码 Memen ...
- 设计模式学习笔记——观察者(Observer)模式
设计模式学习笔记--观察者(Observer)模式 @(设计模式)[设计模式, 观察者模式, Observer] 设计模式学习笔记观察者Observer模式 基本介绍 观察者案例 类图 实现代码 Ob ...
- 设计模式学习笔记——外观(Facade)模式
设计模式学习笔记--外观(Facade)模式 @(设计模式)[设计模式, 外观模式, facade] 设计模式学习笔记外观Facade模式 基本介绍 外观案例 类图 实现代码 Database类 ma ...
- 设计模式学习笔记——装饰(Decorator)模式
设计模式学习笔记--装饰(Decorator)模式 @(设计模式)[设计模式, 装饰模式, decorator] 设计模式学习笔记装饰Decorator模式 基本介绍 装饰案例 类图 实现代码 Dis ...
最新文章
- js之argument小解
- GPU高效通信算法-Ring Allreduce
- 【NLP】6种用于文本分类的开源预训练模型
- 中职生计算机专业600分,来了!超全盘点高职分类中500-600分及以上的高中生能报的专业和院校名单!...
- C语言中关于字符数组输入,scanf没执行
- arm b bl 地址无关码_32位和64位下的arm_pwn初探
- (转载)Fiddler 教程
- Java多线程300毫秒_Java多线程小程序(输出每个线程的毫秒级时间)-Go语言中文社区...
- [TWRP 2.8.4 ] 小米 3W 中文-英文版本 twrp
- algorithm头文件中的函数:remove()与remove_if() 函数,……
- spring + mybatis + 多数据源整合事务
- gem5源码解读se.py以及simulate.py(一)
- 华氏温度转摄氏温度c语言作业,c语言摄氏度与华氏温度如何转换
- UEFI 模式下重新安装系统注意事项
- 【TcaplusDBx黎明觉醒】一路相伴,不负期待
- bzoj5185 [Usaco2018 Jan]Lifeguards
- 第一周 清浊音时域波形与频谱分析以及计算RGB文件三通道的熵
- NFT 金融化:存在哪些机会?面临哪些挑战?
- 沙盘演练工作坊-产品开发_Google认证的Android助理开发人员:考试演练
- 我们从下面几个方面来区别led天花灯和led筒灯