{
    "slug": "visitor_pattern",
    "term": "Visitor Pattern",
    "category": "quality",
    "difficulty": "advanced",
    "short": "A behavioural pattern that separates an algorithm from the objects it operates on — adding new operations to a class hierarchy without modifying those classes.",
    "long": "The Visitor pattern uses double dispatch: the object calls accept(visitor), which calls visitor.visit(this). This allows adding new operations to a stable class hierarchy by writing new Visitor classes rather than adding methods to each node. Common uses: abstract syntax tree traversal, serialisation to different formats, static analysis tools, and document export. The trade-off: adding a new node type requires updating all existing visitors.",
    "aliases": [
        "double dispatch"
    ],
    "tags": [
        "patterns",
        "oop",
        "design-patterns"
    ],
    "misconception": "Visitor requires modifying the visited classes — each class only needs one accept(VisitorInterface $v) method added once; all future operations are new Visitor implementations.",
    "why_it_matters": "Visitor allows adding new operations to a closed class hierarchy without modifying it — ideal for compilers, AST processors, and document renderers where operations change but the node types are stable.",
    "common_mistakes": [
        "Using Visitor when the class hierarchy changes frequently — each new class requires updating all visitors, which is more painful than adding a method to each class.",
        "Not defining a VisitorInterface — without it, the pattern provides no type safety.",
        "Confusing Visitor (new operations, stable classes) with Strategy (interchangeable algorithms, single class).",
        "Implementing Visitor for simple trees where a recursive method on each node is simpler."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "strategy_pattern",
        "composite_pattern",
        "open_closed_principle"
    ],
    "prerequisites": [
        "interfaces",
        "abstract_syntax_tree",
        "open_closed_principle"
    ],
    "refs": [
        "https://refactoring.guru/design-patterns/visitor"
    ],
    "bad_code": "// Without visitor — adding export requires modifying every node:\nclass TextNode {\n    public function toHtml(): string { /* ... */ }\n    public function toPdf(): string { /* ... */ }  // Must add to every node class\n    public function toMarkdown(): string { /* ... */ } // Keeps growing\n}",
    "good_code": "// Visitor — add new export format without touching node classes:\ninterface NodeVisitor {\n    public function visitText(TextNode $node): string;\n    public function visitImage(ImageNode $node): string;\n}\n\nclass TextNode {\n    public function accept(NodeVisitor $v): string { return $v->visitText($this); }\n}\n\nclass MarkdownExporter implements NodeVisitor {\n    public function visitText(TextNode $n): string { return $n->content; }\n    public function visitImage(ImageNode $n): string { return \"![]({$n->src})\"; }\n}",
    "quick_fix": "Use Visitor when you need to add new operations to a class hierarchy without modifying those classes — define accept() in each element, implement the operation in a Visitor class",
    "severity": "low",
    "effort": "high",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/visitor_pattern",
        "html_url": "https://codeclaritylab.com/glossary/visitor_pattern",
        "json_url": "https://codeclaritylab.com/glossary/visitor_pattern.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Visitor Pattern](https://codeclaritylab.com/glossary/visitor_pattern) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/visitor_pattern"
            }
        }
    }
}