跳转到内容

访问者 (Visitor)

访问者 (Visitor) 是一种行为型设计模式,将算法所操作的对象结构分离,使得在不修改各元素类的前提下定义作用于这些元素的新操作。适合“结构稳定、操作常变”的场景。

  • 对象结构(如 AST、文档节点)相对稳定,但需要经常增加针对这些元素的新操作;若在每个元素类里加方法会不断修改元素类。
  • 希望新操作能集中定义、便于扩展,而不改动元素类。
  • 元素 (Element):定义 accept(Visitor v),在 accept 内调用 v.visit(this),把自身交给访问者。
  • 具体元素 (ConcreteElement):实现 accept,访问者通过多态对不同类型的元素执行不同逻辑。
  • 访问者 (Visitor):为每种具体元素声明 visit(ConcreteElementA)visit(ConcreteElementB) 等,实现针对该元素的操作。
  • 具体访问者:实现各 visit 方法,完成具体算法。客户端创建访问者并让元素接受访问,遍历结构时对每个元素调用 accept(visitor)
classDiagram
    class Element {
        <<interface>>
        +accept(Visitor v)* void
    }
    class ConcreteElementA {
        +accept(Visitor v) void
    }
    class Visitor {
        <<interface>>
        +visit(ConcreteElementA e)* void
        +visit(ConcreteElementB e)* void
    }
    class ConcreteVisitor {
        +visit(ConcreteElementA e) void
        +visit(ConcreteElementB e) void
    }
    Element <|.. ConcreteElementA
    Visitor <|.. ConcreteVisitor
    ConcreteElementA ..> Visitor : accept
public interface Element {
void accept(Visitor v);
}
public class ConcreteElementA implements Element {
@Override
public void accept(Visitor v) {
v.visit(this);
}
}
public interface Visitor {
void visit(ConcreteElementA e);
}
public class ConcreteVisitor implements Visitor {
@Override
public void visit(ConcreteElementA e) {
System.out.println("Visitor 访问 ConcreteElementA");
}
}
Element el = new ConcreteElementA();
el.accept(new ConcreteVisitor()); // 输出: Visitor 访问 ConcreteElementA

访问者把“对结构的操作”从元素中抽离到访问者中,便于增加新操作而不改元素类;代价是增加新元素类型需改访问者接口,适合元素类型稳定、操作多变的场景。