← Back to Home
Visitor Pattern
Lets you define a new operation without changing the classes of the elements on which it operates.
What is it?
The Visitor pattern separates algorithms from the objects on which they operate, letting you add new operations without modifying those objects.
Example
interface Visitor { visitCircle(circle: Circle): string; visitSquare(square: Square): string; } interface Shape { accept(visitor: Visitor): string; } class Circle implements Shape { constructor(public radius: number) {} accept(visitor: Visitor): string { return visitor.visitCircle(this); } } class Square implements Shape { constructor(public side: number) {} accept(visitor: Visitor): string { return visitor.visitSquare(this); } } class AreaCalculator implements Visitor { visitCircle(circle: Circle): string { const area = Math.PI * circle.radius ** 2; return `Area of Circle: ${area.toFixed(2)}`; } visitSquare(square: Square): string { const area = square.side ** 2; return `Area of Square: ${area}`; } } const shape: Shape = new Circle(5); const visitor = new AreaCalculator(); console.log(shape.accept(visitor));
Common Uses
- Object structures with many unrelated operations
- Compilers (AST traversal)
- Data structure traversal + operations
When to Use
- You want to separate logic from data structures
- Frequent need to perform unrelated operations on objects
Caution
- Adding a new type of shape requires updating all visitors
- Can be overkill for small object hierarchies