设计模式学习笔记——访问者(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角色)声明一个用于访问xxxxxvisit(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)模式相关推荐

  1. 设计模式学习笔记--访问者(Visitor)模式

    写在模式学习之前 什么是设计模式:在我们进行程序设计时,逐渐形成了一些典型问题和问题的解决方案,这就是软件模式:每一个模式描述了一个在我们程序设计中经常发生的问题,以及该问题的解决方案:当我们碰到模式 ...

  2. 设计模式学习笔记——解释器(Interpreter)模式

    设计模式学习笔记--解释器(Interpreter)模式 @(设计模式)[设计模式, 解释器模式, Interpreter] 设计模式学习笔记解释器Interpreter模式 基本介绍 解释器案例 类 ...

  3. 设计模式学习笔记——命令(Command)模式

    设计模式学习笔记--命令(Command)模式 @(设计模式)[设计模式, 命令模式, command] 设计模式学习笔记命令Command模式 基本介绍 命令案例 类图 实现代码 Command接口 ...

  4. 设计模式学习笔记——代理(Proxy)模式

    设计模式学习笔记--代理(Proxy)模式 @(设计模式)[设计模式, 代理模式, proxy] 设计模式学习笔记代理Proxy模式 基本介绍 代理案例 类图 实现代码 Printable接口 Pri ...

  5. 设计模式学习笔记——状态(State)模式框架

    设计模式学习笔记--状态(State)模式框架 @(设计模式)[设计模式, 状态模式, State] 设计模式学习笔记状态State模式框架 基本介绍 状态案例 类图 实现代码 State接口 Day ...

  6. 设计模式学习笔记——备忘录(Memento)模式

    设计模式学习笔记--备忘录(Memento)模式 @(设计模式)[设计模式, 备忘录模式, memento] 设计模式学习笔记备忘录Memento模式 基本介绍 备忘录案例 类图 实现代码 Memen ...

  7. 设计模式学习笔记——观察者(Observer)模式

    设计模式学习笔记--观察者(Observer)模式 @(设计模式)[设计模式, 观察者模式, Observer] 设计模式学习笔记观察者Observer模式 基本介绍 观察者案例 类图 实现代码 Ob ...

  8. 设计模式学习笔记——外观(Facade)模式

    设计模式学习笔记--外观(Facade)模式 @(设计模式)[设计模式, 外观模式, facade] 设计模式学习笔记外观Facade模式 基本介绍 外观案例 类图 实现代码 Database类 ma ...

  9. 设计模式学习笔记——装饰(Decorator)模式

    设计模式学习笔记--装饰(Decorator)模式 @(设计模式)[设计模式, 装饰模式, decorator] 设计模式学习笔记装饰Decorator模式 基本介绍 装饰案例 类图 实现代码 Dis ...

最新文章

  1. js之argument小解
  2. GPU高效通信算法-Ring Allreduce
  3. 【NLP】6种用于文本分类的开源预训练模型
  4. 中职生计算机专业600分,来了!超全盘点高职分类中500-600分及以上的高中生能报的专业和院校名单!...
  5. C语言中关于字符数组输入,scanf没执行
  6. arm b bl 地址无关码_32位和64位下的arm_pwn初探
  7. (转载)Fiddler 教程
  8. Java多线程300毫秒_Java多线程小程序(输出每个线程的毫秒级时间)-Go语言中文社区...
  9. [TWRP 2.8.4 ] 小米 3W 中文-英文版本 twrp
  10. algorithm头文件中的函数:remove()与remove_if() 函数,……
  11. spring + mybatis + 多数据源整合事务
  12. gem5源码解读se.py以及simulate.py(一)
  13. 华氏温度转摄氏温度c语言作业,c语言摄氏度与华氏温度如何转换
  14. UEFI 模式下重新安装系统注意事项
  15. 【TcaplusDBx黎明觉醒】一路相伴,不负期待
  16. bzoj5185 [Usaco2018 Jan]Lifeguards
  17. 第一周 清浊音时域波形与频谱分析以及计算RGB文件三通道的熵
  18. NFT 金融化:存在哪些机会?面临哪些挑战?
  19. 沙盘演练工作坊-产品开发_Google认证的Android助理开发人员:考试演练
  20. 我们从下面几个方面来区别led天花灯和led筒灯

热门文章

  1. 《算法》笔记 17 - 数据压缩
  2. Django---启动admin的报no such table: auth_user错误
  3. 母函数 入门 + 模板
  4. admin 系统被嵌套在第三方系统中的跨域异常
  5. mcu比较器技巧和诀窍_如何准备技术面试-技巧和窍门,以帮助您表现最好
  6. ubuntu安装hadoop2.9.2
  7. 尝试改写新浪网分类资讯爬虫2
  8. LeetCode题 - 83. 删除排序链表中的重复元素 python实现
  9. Flask-SQLALchemy 连接数据库
  10. Python sys模块的使用