Why this matters
Imagine a document model with Circle, Rectangle, and Triangle. You need to add JSON export, XML export, and SVG rendering. Adding each operation as a method on every class violates the Open/Closed Principle — you're modifying stable code. The Visitor pattern externalizes operations: a JSONExportVisitor knows how to handle every shape; shapes only need to call accept(visitor). Adding a new export is a new class, not a change to existing ones.
The problem
Bad
The solution
Good
Double dispatch in disguise
Visitor is the classic solution to the "double dispatch" problem — dispatching based on the types of two objects (visitor type and element type). When circle.accept(jsonVisitor) calls jsonVisitor.visitCircle(this), the language resolves both the element's type (Circle) and the visitor's type (JSONExportVisitor). Compiler AST walkers, expression evaluators, and document transformers all use this technique extensively.
Key takeaway
Visitor is the answer to "I need to add a new operation to a stable class hierarchy without touching it" — the operation travels to the data, not the other way.