Visitor Pattern Pattern
Lets you separate algorithms from the objects on which they operate by using Double Dispatch.
A tax auditor visiting different properties (Residential home, Commercial factory, Agricultural farm). Each property accepts the auditor (`property.accept(auditor)`), and the auditor executes property-specific tax calculations without changing the property's class.
Interactive Runtime Simulator
Test and tweak inputs dynamicallyInteractive Visitor Pattern SimulatorLIVE PLAYGROUND
Interact with the controls below to see how this design pattern executes in memory at runtime.
Polluting domain model classes (e.g. `Circle`, `Rectangle`, `Dot`) with unrelated exporting, linting, or auditing code.
Define a Visitor interface with an `export(Circle)`, `export(Rectangle)` method for each element type. Elements implement `accept(Visitor)` and dispatch `visitor.export(this)` (Double Dispatch).
Pattern Structure & Participants
| Participant | Role & Responsibility | Type |
|---|---|---|
| Visitor (Interface) | Declares visit(ConcreteElementA), visit(ConcreteElementB) | interface |
| Element (Interface) | Declares accept(Visitor) | interface |
| XmlExportVisitor, JsonExportVisitor | Concrete operations over all elements | class |
- element.accept(visitor) -> executes visitor.visit(element)
- New operations are added by writing a new Visitor class without touching Elements
Production Code Implementation
public interface Shape {
void accept(Visitor visitor);
}
public interface Visitor {
void visitCircle(Circle circle);
void visitRectangle(Rectangle rect);
}
public class Circle implements Shape {
public int radius = 10;
public void accept(Visitor visitor) { visitor.visitCircle(this); }
}
public class Rectangle implements Shape {
public int width = 20, height = 30;
public void accept(Visitor visitor) { visitor.visitRectangle(this); }
}
// Adding new export operation without modifying Circle or Rectangle!
public class SvgExportVisitor implements Visitor {
public void visitCircle(Circle c) {
System.out.println("<circle r='" + c.radius + "' />");
}
public void visitRectangle(Rectangle r) {
System.out.println("<rect width='" + r.width + "' height='" + r.height + "' />");
}
}- •When you need to perform an operation on all elements of a complex object structure (such as an AST tree).
- •When an object structure rarely changes, but you frequently need to define new operations over it.
- •When the element hierarchy changes frequently (adding a new Element requires updating every single Visitor interface and class).
Staff Engineering Interview Insights & Gotchas
- Explain 'Double Dispatch': the method that gets executed depends on both the type of the receiver AND the type of the argument.