Home/Learn/Low Level Design/Visitor Pattern

Visitor Pattern

Advanced
Behavioral Patterns

Lets you add new operations to an object structure without modifying the classes, using double dispatch.

Overview

Visitor separates algorithms from the object structure they operate on. A Visitor interface declares one visit() method per ConcreteElement type. Each ConcreteElement implements accept(Visitor v) which calls v.visit(this) — this is double dispatch: the runtime type of both the element and the visitor determine which visit() method executes. Adding a new operation means adding a new Visitor class (OCP for operations). The downside: adding a new element type requires updating all Visitors (OCP violation for elements). Best for stable element hierarchies with frequently changing operations.

Visitor with AST (Expression Tree)

An arithmetic expression tree where multiple operations (evaluate, print, simplify) are implemented as separate Visitors without touching the expression node classes.

Java — Visitor on Expression AST
// Visitor interface — one method per element type
public interface ExpressionVisitor<T> {
    T visitNumber(NumberExpr expr);
    T visitAdd(AddExpr expr);
    T visitMultiply(MultiplyExpr expr);
}

// Element interface
public interface Expression {
    <T> T accept(ExpressionVisitor<T> visitor);
}

// Concrete Elements
public class NumberExpr implements Expression {
    public final double value;
    public NumberExpr(double value) { this.value = value; }

    @Override
    public <T> T accept(ExpressionVisitor<T> visitor) {
        return visitor.visitNumber(this); // double dispatch
    }
}

public class AddExpr implements Expression {
    public final Expression left, right;
    public AddExpr(Expression left, Expression right) {
        this.left = left; this.right = right;
    }

    @Override
    public <T> T accept(ExpressionVisitor<T> visitor) {
        return visitor.visitAdd(this);
    }
}

public class MultiplyExpr implements Expression {
    public final Expression left, right;
    public MultiplyExpr(Expression left, Expression right) {
        this.left = left; this.right = right;
    }

    @Override
    public <T> T accept(ExpressionVisitor<T> visitor) {
        return visitor.visitMultiply(this);
    }
}

// Visitor 1: Evaluate
public class EvaluateVisitor implements ExpressionVisitor<Double> {
    @Override public Double visitNumber(NumberExpr e)   { return e.value; }
    @Override public Double visitAdd(AddExpr e)         { return e.left.accept(this) + e.right.accept(this); }
    @Override public Double visitMultiply(MultiplyExpr e) { return e.left.accept(this) * e.right.accept(this); }
}

// Visitor 2: Pretty Print
public class PrintVisitor implements ExpressionVisitor<String> {
    @Override public String visitNumber(NumberExpr e)     { return String.valueOf(e.value); }
    @Override public String visitAdd(AddExpr e)           { return "(" + e.left.accept(this) + " + " + e.right.accept(this) + ")"; }
    @Override public String visitMultiply(MultiplyExpr e) { return "(" + e.left.accept(this) + " * " + e.right.accept(this) + ")"; }
}

// Usage — (3 + 4) * 2
Expression ast = new MultiplyExpr(
    new AddExpr(new NumberExpr(3), new NumberExpr(4)),
    new NumberExpr(2));

System.out.println(ast.accept(new PrintVisitor()));    // ((3.0 + 4.0) * 2.0)
System.out.println(ast.accept(new EvaluateVisitor())); // 14.0

Key Points to Remember

  • 1Double dispatch: accept(visitor) calls visitor.visit(this) — both element type and visitor type are resolved at runtime.
  • 2Adding a new operation = new Visitor class (OCP). Adding a new element = update all Visitors (OCP violation).
  • 3Best for stable element hierarchies (e.g. AST nodes) with frequently added operations.
  • 4Java's instanceof pattern matching (Java 16+) and sealed classes can replace Visitor in some cases.
  • 5Visitor breaks encapsulation slightly — Visitor methods need access to element internals.

Interview Questions

Sign in to ask Aria
1

What is double dispatch and how does Visitor pattern use it?

HardGoogle
2

What are the tradeoffs of Visitor: when does adding a new element become painful?

MediumAmazon
3

How would you use Java sealed classes to replace Visitor in Java 17+?

HardNetflix
4

Name a real-world use case for Visitor pattern.

EasyMicrosoft

Ask Aria about Visitor Pattern

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…