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
↓ accept(visitor)
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)
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).
Back to all topics →