访问者模式(Visitor Pattern)

在访问者模式中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

核心组成

  1. 访问者接口(Visitor)

定义对每一个元素类可以执行的操作,通常按元素类型重载方式。

1
2
3
4
public interface Vistor {
void visitConcreteElementA(ConcreteElementA elementA);
void visitConcreteElementB(ConcreteElementB elementB);
}
  1. 具体访问者类(Concrete Visitor)

实现每个操作的具体逻辑。

1
2
3
4
5
6
7
8
9
10
11
public class ConcreteVisitor implements Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA elementA) {
System.out.println("访问者处理元素 A:" + elementA.operation());
}

@Override
public void visitConcreteElementB(ConcreteElementB elementB) {
System.out.println("访问者处理元素 B:" + elementB.operation());
}
}
  1. 元素接口(Element)

声明一个接收访问者的方法accept

1
2
3
public interface Element {
void accept(Visitor visitor);
}
  1. 具体元素类(Concrete Element)

实现accept方法,调用访问者的对应方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ConcreteElementA implements Element {
public String operation() {
return "元素 A 的内容";
}

@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
}

public class ConcreteElementB implements Element {
public String operation() {
return "元素 B 的内容";
}

@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
}

  1. 对象结构(Object Structure)

管理一组元素,并提供一个让访问者访问所有元素的接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.ArrayList;
import java.util.List;

public class ObjectStructure {
private List<Element> elements = new ArrayList<>();

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

public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}
  1. 客户端示例
1
2
3
4
5
6
val structure = ObjectStructure()
structure.add(ConcreteElementA())
structure.add(ConcreteElementB())

val visitor = ConcreteVisitor()
structure.accept(visitor)

适用场景

  • 数据结构相对稳定,但对其操作经常扩展的系统。
  • 编译器设计中用于遍历语法树。
  • 报表生成、日志记录、渲染引擎等需统一处理多种对象的场景。

Java中的典型应用

  • Java编译器工具(如javac)使用访问者模式遍历AST(抽象语法树).
  • XML/JSON解析框架中对节点进行统一访问处理。
  • Spring框架中用于配置解析和依赖注入的访问逻辑。

变体与替代方案

  • 双亲派(Double Dispatch): 访问者模式的核心机制。
  • 策略模式: 时和单一结构多算法,但不具备访问者对多种元素的支持能力。
  • 责任链模式: 侧重请求传递而非统一访问。