design·lab

Behavioral pattern

Visitor

A stable set of elements accepts a visitor — so you can add a whole new operation over all of them without touching a single element class.

✗ The problem

Every new operation touches every class

Circle, Square, Triangle rarely change — but you keep needing new ops: area, export to SVG, describe. Each one means editing every element (or a big type-switch).

function area(shape) {
  if (shape.type === 'circle')   return Math.PI * shape.r ** 2;
  if (shape.type === 'square')   return shape.side ** 2;
  if (shape.type === 'triangle') return 0.5 * shape.base * shape.h;
}
function toSVG(shape)   { /* …same type-switch, again */ }
function describe(shape) { /* …and again */ }
// new op? write a NEW switch over every type.
Operations are smeared across every element class (or duplicated in giant switches) — each new op touches them all.
✓ The pattern

Elements accept a visitor (double dispatch)

Each element just knows how to accept a visitor. Each visitor implements one method per element type. New operation = new visitor class.

class Circle { accept(v){ return v.visitCircle(this); } }

class AreaVisitor {
  visitCircle(c){ return Math.PI * c.r * c.r; }
  visitSquare(s){ return s.side * s.side; }
}
Circle
accept(v)
Square
accept(v)
↓ accept(visitor)
AreaVisitor
ExportVisitor
✓ See it live

Pick a visitor — run it over every shape

Same three shapes, same shape classes. Pick a visitor and it runs across all of them — proving you added an operation WITHOUT changing a single shape class.

⚪ Circle
◼ Square
▲ Triangle
Pick a visitor above ▲

Tip: switch visitors — the shape classes never change.

✓ Takeaway

New operations, unchanged elements

  • Add an operation = add a visitor class. Element classes stay untouched.
  • Great fit: ASTs, compilers, document trees — structure is stable, operations grow.
  • Caution: adding a new ELEMENT type forces updating every visitor — the trade-off is inverted from most patterns.
🎯 Principle applied: Visitor gives Open/Closed for operations (new op = new visitor, elements untouched) and keeps each operation in one place (SRP).