3.11设计模式——Visitor 访问者模式(行为型)

意图

表示一个作用于某对象结构中的各元素的操作。它允许在不改变各元素的类的前提下定义作用于这些元素的新操作。

结构

  • Visitor(访问者)为该对象结构中ConcreteElement(具体元素)的每一个类声明一个Visit操作,该操作的名字和特征标识了发送Visit请求给该访问者的那个类,这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。
  • ConcreteVisitor(具体访问者)实现每个有Visitor声明的操作,每个操作实现本算法的一部分,而算法片段乃是对应于结构中对象的类。ConcreteVisitor为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累计结果。
  • Element(元素)定义以一个访问者为参数的Accept操作。
  • ConcreteElement(具体元素)实现以一个访问者为参数的Accept操作。
  • ObjectStructure(对象结构)能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个组合或者是一个集合,如一个列表或一个无序集合。

适用性

  • 一个对象结构包含很多类对象,它们有不同的接口,而用户想对这些对象实施一些依赖于具体类的操作。
  • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而又想要避免这些操作污染这些对象的类,Visitor使得用户可以将相关的操作集中起来定义再一个类中。当该对象结构被很多应用共享是,用Visitor模式让每个应用仅包含需要用到的操作。
  • 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对独有访问者的接口,这可能需要很大的代价。如果对象结构经常改变,那么可能还是在这些类中定义这些操作较好。

代码示例

java 复制代码
// Element接口
interface Element {
    void accept(Visitor visitor);
}

// ConcreteElement具体元素类
class ConcreteElementA implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visitConcreteElementA(this);
    }
}

class ConcreteElementB implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visitConcreteElementB(this);
    }
}

// Visitor访问者接口
interface Visitor {
    void visitConcreteElementA(ConcreteElementA element);
    void visitConcreteElementB(ConcreteElementB element);
}

// ConcreteVisitor具体访问者类
class ConcreteVisitor implements Visitor {
    @Override
    public void visitConcreteElementA(ConcreteElementA element) {
        System.out.println("访问者正在访问 ConcreteElementA");
    }

    @Override
    public void visitConcreteElementB(ConcreteElementB element) {
        System.out.println("访问者正在访问 ConcreteElementB");
    }
}

// ObjectStructure对象结构类
class ObjectStructure {
    private List<Element> elements = new ArrayList<>();

    public void addElement(Element element) {
        elements.add(element);
    }

    public void removeElement(Element element) {
        elements.remove(element);
    }

    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

// 示例用法
public class VisitorPatternExample {
    public static void main(String[] args) {
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.addElement(new ConcreteElementA());
        objectStructure.addElement(new ConcreteElementB());

        Visitor visitor = new ConcreteVisitor();
        objectStructure.accept(visitor);
    }
}
  1. Element(元素)接口定义了一个接受访问者的方法 accept(Visitor visitor),该方法允许访问者访问元素。

  2. ConcreteElementA 和 ConcreteElementB 是具体元素类,它们实现了 Element 接口,并在 accept 方法中调用访问者的相应方法,将自身作为参数传递给访问者。

  3. Visitor(访问者)接口声明了访问具体元素的方法,例如 visitConcreteElementAvisitConcreteElementB

  4. ConcreteVisitor(具体访问者)类实现了 Visitor 接口,提供了对具体元素的访问方法的具体实现。

  5. ObjectStructure(对象结构)类维护了一个元素列表,并提供了一个接受访问者的方法 accept,在该方法中遍历元素列表,调用每个元素的 accept 方法,让访问者访问每个元素。

相关推荐
翊谦2 小时前
Java Agent开发 Milvus 向量数据库安装
java·数据库·milvus
晓晓hh2 小时前
JavaSE学习——迭代器
java·开发语言·学习
查古穆3 小时前
栈-有效的括号
java·数据结构·算法
Java面试题总结3 小时前
Spring - Bean 生命周期
java·spring·rpc
硅基诗人3 小时前
每日一道面试题 10:synchronized 与 ReentrantLock 的核心区别及生产环境如何选型?
java
014-code3 小时前
String.intern() 到底干了什么
java·开发语言·面试
摇滚侠4 小时前
JAVA 项目教程《苍穹外卖-12》,微信小程序项目,前后端分离,从开发到部署
java·开发语言·vue.js·node.js
楚国的小隐士4 小时前
为什么说Rust是对自闭症谱系人士友好的编程语言?
java·rust·编程·对比·自闭症·自闭症谱系障碍·神经多样性
春花秋月夏海冬雪4 小时前
代码随想录刷题 - 贪心Part1
java·算法·贪心·代码随想录
野生技术架构师4 小时前
2026年牛客网最新Java面试题总结
java·开发语言