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 方法,让访问者访问每个元素。

相关推荐
qq13267029407 小时前
ARM版统信UOS桌面安装JDK
java·jdk·arm·统信uos·毕昇jdk 11
码头工人7 小时前
【架构师系列】风控场景下超高并发频次计算服务的设计与实践
java·架构·风控·反爬
长不大的蜡笔小新7 小时前
私人健身房管理系统
java·javascript·spring boot
hdsoft_huge8 小时前
Java 实现高效查询海量 geometry 及 Protobuf 序列化与天地图前端分片加载
java·前端·状态模式
xiaowu0808 小时前
IEnumerable、IEnumerator接口与yield return关键字的相关知识
java·开发语言·算法
笨手笨脚の8 小时前
深入理解 Java 虚拟机-01 JVM 内存模型
java·jvm··虚拟机栈·方法区
王家视频教程图书馆8 小时前
android java 开发网路请求库那个好用请列一个排行榜
android·java·开发语言
花卷HJ8 小时前
Android 文件工具类 FileUtils(超全封装版)
android·java
rchmin8 小时前
ThreadLocal内存泄漏机制解析
java·jvm·内存泄露
黎雁·泠崖8 小时前
Java 方法栈帧深度解析:从 JIT 汇编视角,打通 C 与 Java 底层逻辑
java·c语言·汇编