java23种设计模式-访问者模式

访问者模式(Visitor Pattern)学习笔记


编程相关书籍分享:https://blog.csdn.net/weixin_47763579/article/details/145855793


一、模式定义

🌐 行为型设计模式,通过将算法与对象结构分离,在不修改现有对象结构的前提下定义新操作。符合开闭原则(对扩展开放,对修改关闭)。

二、类图(Mermaid表示)

accept()
accept()
«interface»
Visitor
+visitConcreteElementA(ConcreteElementA)
+visitConcreteElementB(ConcreteElementB)
ConcreteVisitor1
+visitConcreteElementA(ConcreteElementA)
+visitConcreteElementB(ConcreteElementB)
ConcreteVisitor2
+visitConcreteElementA(ConcreteElementA)
+visitConcreteElementB(ConcreteElementB)
«interface»
Element
+accept(Visitor)
ConcreteElementA
+accept(Visitor)
+operationA()
ConcreteElementB
+accept(Visitor)
+operationB()
ObjectStructure
-elements: List<Element>
+addElement(Element)
+removeElement(Element)
+accept(Visitor)

三、核心组成

  1. Visitor(访问者接口)

    • 声明visit方法集合(参数类型对应具体元素类型)
  2. ConcreteVisitor(具体访问者)

    • 实现visit方法,定义对具体元素的操作
  3. Element(元素接口)

    • 定义accept方法接收访问者对象
  4. ConcreteElement(具体元素)

    • 实现accept方法,调用访问者的visit方法
  5. ObjectStructure(对象结构)

    • 维护元素集合,提供遍历元素的接口

四、Java实现示例

// 元素接口
interface Element {
    void accept(Visitor visitor);
}

// 具体元素A
class ConcreteElementA implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    public String operationA() {
        return "ElementA Operation";
    }
}

// 具体元素B
class ConcreteElementB implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    public String operationB() {
        return "ElementB Operation";
    }
}

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

// 具体访问者1
class ConcreteVisitor1 implements Visitor {
    public void visit(ConcreteElementA element) {
        System.out.println("Visitor1 processing: " + element.operationA());
    }
    public void visit(ConcreteElementB element) {
        System.out.println("Visitor1 processing: " + element.operationB());
    }
}

// 对象结构
class ObjectStructure {
    private List<Element> elements = new ArrayList<>();
    
    public void addElement(Element element) {
        elements.add(element);
    }
    
    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

// 使用示例
public class Client {
    public static void main(String[] args) {
        ObjectStructure structure = new ObjectStructure();
        structure.addElement(new ConcreteElementA());
        structure.addElement(new ConcreteElementB());
        
        Visitor visitor1 = new ConcreteVisitor1();
        structure.accept(visitor1);
    }
}

五、双分派机制

🚀 两次动态绑定

  1. 元素通过accept方法选择接收访问者
  2. 访问者通过visit方法选择处理具体元素类型

六、适用场景

✅ 需要对复杂对象结构(如组合结构)添加新操作
✅ 数据结构稳定但需要频繁添加新算法
✅ 需要分离无关行为避免污染类
✅ 需要运行时选择不同处理逻辑

七、优缺点分析

✔️ 优点

  • 符合单一职责原则
  • 优秀的扩展性(新增访问者不影响现有系统)
  • 集中相关行为

缺点

  • 增加新元素类型困难(需要修改所有访问者)
  • 破坏元素封装性(需要暴露内部状态)
  • 不适用于元素结构频繁变化的场景

八、实际应用

  1. 编译器:语法树分析(类型检查、代码优化)
  2. 文件系统处理:不同格式文件的处理
  3. XML解析:DOM树遍历处理
  4. ASM字节码框架:ClassVisitor体系
  5. JDK示例java.nio.file.FileVisitor

九、相关模式对比

模式关注点
访问者在对象结构上执行操作
迭代器遍历集合元素
组合模式处理树形结构
装饰器动态添加职责

建议结合具体业务场景(如电商订单处理、文档转换工具)进行实践练习,加深对双分派机制的理解。

posted on 2025-02-25 16:33  千里码!  阅读(51)  评论(0)    收藏  举报  来源