visitor
Separate an algorithm from the object structure it operates on, allowing new operations without modifying the classes.
SKILL.mdskills/code-quality/visitor/SKILL.md
GitHubVisitor
Lets you add new operations to an object structure without modifying its classes, by having each element "accept" a visitor and dispatch to the right visitor method.
When to Use
- You need to perform many distinct, unrelated operations on an object structure
- Adding these operations to the classes would pollute them
- The object structure is stable but operations on it change frequently
- Traversal and operation should be separated (ASTs, document models, UI trees)
How to Apply
- Define a
Visitorinterface with avisit(element)overload for each element type - Each element class implements
accept(visitor: Visitor)which callsvisitor.visit(this) - Create concrete visitor classes that implement the operations
- Traverse the structure and call
accept()on each element — visitor handles the type dispatch
Example
interface Visitor {
visitCircle(c: Circle): void;
visitRectangle(r: Rectangle): void;
}
interface Shape { accept(v: Visitor): void; }
class Circle implements Shape {
constructor(readonly radius: number) {}
accept(v: Visitor) { v.visitCircle(this); }
}
class Rectangle implements Shape {
constructor(readonly w: number, readonly h: number) {}
accept(v: Visitor) { v.visitRectangle(this); }
}
class AreaCalculator implements Visitor {
total = 0;
visitCircle(c: Circle) { this.total += Math.PI * c.radius ** 2; }
visitRectangle(r: Rectangle) { this.total += r.w * r.h; }
}
const shapes: Shape[] = [new Circle(5), new Rectangle(4, 6)];
const calc = new AreaCalculator();
shapes.forEach(s => s.accept(calc));
console.log(calc.total); // ~102.54