Visitor模式

Visitor模式Visitor 模式在 Visitor 模式中 数据结构和处理被分离开 我们编写一个表示 访问者 的类来访问数据结构中的元素 并把对各元素的处理交给访问者类 这样 当需要增加新的处理时 我们只需要编写新的访问者 然后让数据结构可以接受访问者的访问即可 示例程序示例程序类图 Visitorpubli publicabstra

Visitor 模式

在Visitor 模式中,数据结构和处理被分离开。我们编写一个表示“访问者”的类来访问数据结构中的元素,并把对各元素的处理交给访问者类。这样,当需要增加新的处理时,我们只需要编写新的访问者,然后让数据结构可以接受访问者的访问即可

示例程序

示例程序类图

类图

Visitor

public abstract class Visitor { 
    public abstract void visit(File file); public abstract void visit(Directory directory); } 

Element

public interface Element { 
    void accept(Visitor v); } 

Entry

public abstract class Entry implements Element { 
    public abstract String getName(); // 获取名字 public abstract int getSize(); // 获取大小 public Entry add(Entry entry) throws FileTreatmentException { 
    // 增加目录条目 throw new FileTreatmentException(); } public Iterator iterator() throws FileTreatmentException { 
    // 生成Iterator throw new FileTreatmentException(); } @Override public String toString() { 
    // 显示字符串 return getName() + " (" + getSize() + ")"; } } 

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 accept(Visitor v) { 
    v.visit(this); } } 

Directory

import java.util.Iterator; import java.util.ArrayList; public class Directory extends Entry { 
    private String name; // 文件夹名字 private ArrayList dir = new ArrayList(); // 目录条目集合 public Directory(String name) { 
    // 构造函数 this.name = name; } @Override public String getName() { 
    // 获取名字 return name; } @Override public int getSize() { 
    // 获取大小 int size = 0; Iterator it = dir.iterator(); while (it.hasNext()) { 
    Entry entry = (Entry)it.next(); size += entry.getSize(); } return size; } @Override public Entry add(Entry entry) { 
    // 增加目录条目 dir.add(entry); return this; } @Override public Iterator iterator() { 
    // 生成Iterator return dir.iterator(); } @Override public void accept(Visitor v) { 
    // 接受访问者的访问 v.visit(this); } } 

ListVisitor

import java.util.Iterator; public class ListVisitor extends Visitor { 
    private String currentdir = ""; // 当前访问的文件夹的名字 @Override public void visit(File file) { 
    // 在访问文件时被调用 System.out.println(currentdir + "/" + file); } @Override public void visit(Directory directory) { 
    // 在访问文件夹时被调用 System.out.println(currentdir + "/" + directory); String savedir = currentdir; currentdir = currentdir + "/" + directory.getName(); Iterator it = directory.iterator(); while (it.hasNext()) { 
    Entry entry = (Entry)it.next(); entry.accept(this); } currentdir = savedir; } } 

FileTreatmentException

public class FileTreatmentException extends RuntimeException { 
    public FileTreatmentException() { 
    } public FileTreatmentException(String msg) { 
    super(msg); } } 

Main

public class Main { 
    public static void main(String[] args) { 
    try { 
    System.out.println("Making root entries..."); Directory rootdir = new Directory("root"); Directory bindir = new Directory("bin"); Directory tmpdir = new Directory("tmp"); Directory usrdir = new Directory("usr"); rootdir.add(bindir); rootdir.add(tmpdir); rootdir.add(usrdir); bindir.add(new File("vi", 10000)); bindir.add(new File("latex", 20000)); rootdir.accept(new ListVisitor()); System.out.println(""); System.out.println("Making user entries..."); Directory yuki = new Directory("yuki"); Directory hanako = new Directory("hanako"); Directory tomura = new Directory("tomura"); usrdir.add(yuki); usrdir.add(hanako); usrdir.add(tomura); yuki.add(new File("diary.html", 100)); yuki.add(new File("Composite.java", 200)); hanako.add(new File("memo.tex", 300)); tomura.add(new File("game.doc", 400)); tomura.add(new File("junk.mail", 500)); rootdir.accept(new ListVisitor()); } catch (FileTreatmentException e) { 
    e.printStackTrace(); } } } 

Visitor模式中登场的角色

1.Visitor(访问者)

Visitor角色负责对数据结构中每个具体的元素(ConcreteElement角色)声明一个用于访问xxxxx的visit(xxxxx)方法。visit(xxxxx)是用于处理xxxxx的方法,负责实现该方法的是ConcreteVisitor角色。在示例程序中,由Visitor类扮演此角色。

2.ConcreteVisitor(具体的访问者)

ConcreteVisitor角色负责实现Visitor角色所定义的接口(API)。它要实现所有的visit(xxxxx)方法,即实现如何处理每个ConcreteElement角色。在示例程序中,由ListVisitor类扮演此角色。如同在ListVisitor中,currentdir字段的值不断发生变化一样,随着visit(xxxxx)处理的进行,ConcreteVisitor角色的内部状态也会不断地发生变化。

3.Element(元素)

Element角色表示Visitor角色的访问对象。它声明了接受访问者的accept方法。accept方法接收到的参数是Visitor角色。在示例程序中,由Element接口扮演此角色。

4.ConcreteElement

ConcreteElement角色负责实现Element角色所定义的接口(API)。在示例程序中,由File类和Directory类扮演此角色。

5.ObjectStructure(对象结构)

ObjectStructure角色负责处理Element角色的集合。ConcreteVisitor角色为每个Element角色都准备了处理方法。在示例程序中,由Directory类扮演此角色(一人分饰两角)。为了让ConcreteVisitor角色可以遍历处理每个Element角色,在示例程序中,我们在Directory类中实现了iterator方法。

通用类图

通用类图

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/199165.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午1:42
下一篇 2026年3月26日 下午1:42


相关推荐

  • 行列式的计算(矩阵外面加个绝对值)

    行列式的计算(矩阵外面加个绝对值)1 写在前面我表示很难过 曾经线代 矩阵学的也不算太差 可惜太久没用 导致现在连最基本的行列式都不会了 以后还是要多用 多用 多用 重要的事情说三遍 2 行列式的计算准则定义 n 阶行列式等于所有取自不同行不同列的 n 个元素的乘积的代数和 这里是 1 2 n 的一个排列 每一项都按下列规则带有符号 当是偶排列时带有正号 当是奇排列时带有负号 这一定义可写成这里表

    2026年3月16日
    1
  • 自己整理的运维面试题,必须会。

    自己整理的运维面试题,必须会。1.mysql主从原理。**Slave开启I/O线程来请求master服务器,请求指定bin-logMaster端收到请求,Master端I/O线程响应请求通过bin-log将内容返给salveSlave将收到的内容存入relay-log中继日志中Slave端SQL实时监测relay-log日志有更新执行完毕之后,Slave端跟master端数据保持一致!**2.DNS原理。…

    2022年6月7日
    44
  • 百度分享到qq空间失败

    百度分享到qq空间失败

    2021年9月19日
    50
  • 扒站工具整站_抓包知乎

    扒站工具整站_抓包知乎前两节说了利用浏览器或者借助仿站工具来扒站,这些方法适用于一般的web站点,对于某些不能在PC端打开的站点就比较困难了。如果只是在后台检验客户端来限制用户浏览,比如你用PC访问的时候自动转到PC页面或

    2022年8月6日
    7
  • Agents and Multi-Agents System 智能与多智能体系统

    Agents and Multi-Agents System 智能与多智能体系统

    2026年3月16日
    3
  • STM32中重定向printf到SWO口[通俗易懂]

    STM32中重定向printf到SWO口[通俗易懂]Keil中调试:用SWO功能替代printf引用网址:http://blog.csdn.net/xiaolei05/article/details/8526021嵌入式软件开发中的一个基本需求就是能通过终端来输出调试信息,一般可通过2种方式实现:一种是使用串口线连接板上的UART和PC上的COM口,通过PC上的超级终端来查看调试信息;另一种则是采用半主机机制,但有可能不被

    2025年6月1日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号