← Home
🏗Crack System Design with DSA AnimatorSystem DesignNEW
🏗 System Design›Behavioral Patterns

👤Visitor Pattern

Represent an operation to be performed on elements of an object structure — define new operations without changing element classes.

📌 Key IdeaEach Element implements accept(Visitor v) → calls v.visitConcrete(this) (double dispatch). Add new visitor class for new operation over stable structure (AST walkers, document exports). Trade-off: adding new element type touches every visitor.
🖼

Visual

👤 Double dispatch
  for (Node n : tree)
      n.accept(visitor);   // Node calls visitor.visit(this)

  class PrintVisitor implements Visitor {
      void visit(PlusExpr e) { ... }
      void visit(LiteralExpr e) { ... }
  }

Operations live in visitors — structure classes stay slim.

✅

When to Use

  • Stable object structure (AST, scene graph) but many orthogonal operations (pretty-print, eval, compile).
  • You want to keep node classes small — behaviour grouped by visitor.
🚫

When NOT to Use

  • Structure churns frequently — each new node type updates all visitors (opposite trade-off to abstract factory pain).
  • Simple iteration — Iterator / Stream suffices.
🚨

Anti-Pattern (What NOT to Do)

One eval with instanceof ladderBadjava
int eval(Expr e) {
    if (e instanceof Literal l) return l.v();
    if (e instanceof Add a) return eval(a.left()) + eval(a.right());
    throw new UnsupportedOperationException();
}
Adding Mul edits this method — open/closed violation.
✅

The Right Way

Visitor — new op = new classGoodjava
interface Expr {
    <T> T accept(ExprVisitor<T> v);
}

interface ExprVisitor<T> {
    T visit(Literal e);
    T visit(Add e);
}

class EvalVisitor implements ExprVisitor<Integer> {
    public Integer visit(Literal e) { return e.v(); }
    public Integer visit(Add e) {
        return e.left().accept(this) + e.right().accept(this);
    }
}
New traversal (PrintVisitor) doesn't touch Literal / Add classes.
⚖️

Pros & Cons

👍 Pros
  • Groups related behaviour across types (XmlExportVisitor).
  • Accumulates state in visitor fields during traversal.
👎 Cons
  • Adding new element type forces changes across visitors.
  • Indirection — double dispatch unfamiliar to some readers.
🔀

Common Confusions Cleared Up

Visitor vs Iterator

Iterator walks structure without knowing node-specific operations. Visitor performs typed operations per node via visit overloads.

🎤

Interview Q&A

🔮

Likely Follow-up Questions

  • Acyclic Visitor variant — when would you use it?
🧾

Quick Cheat Sheet

IntentNew ops over stable structure.
Mechanismaccept + visit overloads.
Trade-offOps easy; new node type costly.
🔗

Related Topics