The Visitor Pattern is a classic behavioral design pattern that allows developers to define new operations on complex object structures (such as Abstract Syntax Trees, document models, or composite hierarchies) without modifying the classes of the elements on which it operates.
This guide details double dispatch mechanics, AST traversal pipelines, memory safety, and modern pattern matching language alternatives.
Double Dispatch Sequence:
[ Client Code ] ---> `element.accept(visitor)`
|
v
[ ConcreteElementNode ] ---> `visitor.visit(this)`
|
v
[ ConcreteVisitor ] <--- Executes specific logic for ConcreteElementNode!
// Element Interface
public interface AstNode {
<R> R accept(AstVisitor<R> visitor);
}
// Concrete Elements
public record BinaryOpNode(AstNode left, String op, AstNode right) implements AstNode {
@Override
public <R> R accept(AstVisitor<R> visitor) {
return visitor.visitBinaryOp(this);
}
}
// Visitor Interface
public interface AstVisitor<R> {
R visitBinaryOp(BinaryOpNode node);
R visitLiteral(LiteralNode node);
}