博客
关于我
大白话聊访问者模式:从入门到实践
阅读量:416 次
发布时间:2019-03-06

本文共 2727 字,大约阅读时间需要 9 分钟。

访问者模式:从理论到实践

访问者模式是一种软件设计模式,其核心思想是通过封装操作,实现对数据结构的灵活扩展。这种模式在软件开发中广泛应用,尤其是在需要对已有代码库进行扩展时,能够有效避免对原有代码的修改。

访问者模式的定义

访问者模式的核心思想是:在不改变数据结构的前提下,定义新的操作。具体而言,访问者模式通过定义一个接口(Visitor),将对数据结构中各元素的操作封装进去。这样,系统的核心逻辑可以保持不变,而新增的功能可以通过实现不同的访问者类来实现。

以科学家接受采访的情景为例:访谈流程是固定的,包括三个部分:学校经历、工作经历和科研成果。但不同记者的采访内容会有所不同。这种变化可以通过访问者模式实现:定义一个Visitor接口,分别在每个访问者类中实现对应的采访方法。

访问者模式的实现

###Visitor接口Visitor接口定义了所有可能的访问操作。例如:

public interface Visitor {    void askSchoolExperience(String name);    void askWorkExperience(String name);    void askScienceAchievement(String name);}

###具体访问者类每个具体的访问者类实现Visitor接口,定义自己的访问逻辑。例如,新华社的记者可能更关心科研成果,而青年报的记者可能更关注精神层面的东西。

public class XinhuaVisitor implements Visitor {    @Override    public void askSchoolExperience(String name) {        System.out.println("请问" + name + ":在学校取得的最大成就是什么?");    }    //其他方法类似...}

###被访问者类被访问者类(Element)通过一个accept方法接收访问者对象。例如,科学家的类可以有一个accept方法,将访问者传递给内部逻辑。

public class Scientist {    private Visitor visitor;    private String name;        public Scientist(String name) {        this.name = name;    }        public void accept(Visitor visitor) {        this.visitor = visitor;    }        public void interview() {        visitor.askSchoolExperience(name);        visitor.askWorkExperience(name);        visitor.askScienceAchievement(name);    }}

###访问过程通过上述实现,可以看到访问者模式的核心逻辑:访问者通过interface定义了操作,具体访问者实现这些操作,被访问者通过accept方法将访问者接收进来,最后在interview方法中调用访问者的操作。

这种设计使得访谈流程固定不变,而采访内容的变化可以通过不同的访问者实现。

访问者模式的实际应用

###文件树遍历在JDK中,FileVisitor接口定义了文件遍历的操作。不同的遍历器可以实现不同的操作,比如统计文件数或打印文件名。

public interface FileVisitor {    FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs);    FileVisitResult visitFile(T file, BasicFileAttributes attrs);    FileVisitResult postVisitDirectory(T dir, IOException exc);}

###字节码修改(ASM)ASM框架中的ClassVisitor类通过继承FileVisitor接口,实现了对字节码的修改。ClassReader类作为被访问者,负责读取和解析字节码。

public class ClassReader {    public ClassReader(byte[] classfile) {        //解析字节码并存储为Class对象    }        public ClassVisitor accept(ClassVisitor visitor) {        //调用visitor的各个方法        visitor.visitClass(...);        return visitor;    }}

ClassWriter类则是ClassVisitor的实现类,负责输出修改后的字节码。

public class ClassWriter implements ClassVisitor {    public ClassWriter(ClassVisitor visitor) {        //初始化    }        @Override    public ClassVisitor visitClass(...) {        //修改字节码        return this;    }        //其他方法类似...}

这种设计使得字节码的修改与原有框架无关,提高了扩展性。

当然使用访问者模式

访问者模式在以下场景下表现出色:

  • 需要对已有代码库进行扩展,而无需修改原有代码。
  • 需要支持多种操作,但核心逻辑保持不变。
  • 需要通过参数传递状态或行为,但不想改变已有结构。
  • ###优点

  • 高可维护性:固定不变的逻辑只需修改访问者类。
  • 灵活扩展性:新增功能只需添加新的访问者类。
  • 减少耦合度:减少被访问者与访问者之间的依赖。
  • ###缺点

  • 增加了复杂性:引入多个类需要更多的管理。
  • 被访问者难以扩展:一旦被访问者结构固定,修改难度大。
  • 参考资料

  • 《设计模式》
  • JDK的FileVisitor接口
  • ASM框架文档
  • 访问者模式是一种强大的设计模式,其核心在于通过抽象化的接口实现灵活的扩展。如果你的项目需要对已有代码进行扩展,而无需频繁修改核心逻辑,那么访问者模式绝对值得考虑。

    转载地址:http://riakz.baihongyu.com/

    你可能感兴趣的文章
    MYSQL 查看最大连接数和修改最大连接数
    查看>>
    MySQL 查看有哪些表
    查看>>
    mysql 查看锁_阿里/美团/字节面试官必问的Mysql锁机制,你真的明白吗
    查看>>
    MySql 查询以逗号分隔的字符串的方法(正则)
    查看>>
    MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT 、分页查询的优化、合理使用连接、子查询的优化)(上)
    查看>>
    mysql 查询数据库所有表的字段信息
    查看>>
    【Java基础】什么是面向对象?
    查看>>
    mysql 查询,正数降序排序,负数升序排序
    查看>>
    MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)...
    查看>>
    mysql 死锁 Deadlock found when trying to get lock; try restarting transaction
    查看>>
    mysql 死锁(先delete 后insert)日志分析
    查看>>
    MySQL 死锁了,怎么办?
    查看>>
    MySQL 深度分页性能急剧下降,该如何优化?
    查看>>
    MySQL 深度分页性能急剧下降,该如何优化?
    查看>>
    MySQL 添加列,修改列,删除列
    查看>>
    mysql 添加索引
    查看>>
    MySQL 添加索引,删除索引及其用法
    查看>>
    mysql 状态检查,备份,修复
    查看>>
    MySQL 用 limit 为什么会影响性能?
    查看>>
    MySQL 用 limit 为什么会影响性能?有什么优化方案?
    查看>>