Visitor helps when you have a stable object structure but need to add multiple new operations across it cleanly.
Represent an operation to be performed on elements of an object structure, letting you define new operations without changing the element classes.
What the pattern is trying to do
Represent an operation to be performed on elements of an object structure, letting you define new operations without changing the element classes.
What force creates the need
You need new operations across an existing object structure, but changing every element class repeatedly would be painful.
How the pattern responds
Separate operations into visitor objects while element classes accept visitors through a stable protocol.
How the moving parts fit together
Elements expose an accept method, and visitors implement type-specific operations for each element kind.
Java example in the Order Management domain
package org.javaomnibus.ecommerce.gof.behavioral;
public interface OrderNode {
void accept(OrderNodeVisitor visitor);
}
public interface OrderNodeVisitor {
void visit(ProductOrderNode node);
}
public final class ProductOrderNode implements OrderNode {
@Override
public void accept(OrderNodeVisitor visitor) {
visitor.visit(this);
}
}
Step by step
- The object structure stays stable while new operations move into visitors.
- Visitors are useful when many cross-cutting operations target the same structure.
- This pattern is most justified when element types are stable but operations keep growing.
- Visitor is more specialized than many other GoF patterns and should be applied deliberately.
Where this pattern helps
- When you have a stable structure and many operations over it
- When adding operations without editing element classes repeatedly matters
When a simpler design is better
- When the element hierarchy changes often
- When the added complexity outweighs the benefit of externalized operations
What this pattern costs
- Adding a new element type can force updates across all visitors
- The pattern can feel heavy in ordinary business code
How this fits today
Visitor still matters in compilers, AST processing, reporting pipelines, and rule/tree processing, though many Java applications do not need it daily.
Where teams get it wrong
Applying Visitor to unstable domain models usually creates more maintenance burden than design benefit.