{
    "slug": "strategy_pattern",
    "term": "Strategy Pattern",
    "category": "general",
    "difficulty": "intermediate",
    "short": "Defines a family of interchangeable algorithms behind a common interface, allowing the algorithm to be selected at runtime.",
    "long": "The Strategy pattern encapsulates each algorithm in its own class implementing a common interface, making them interchangeable. The context class accepts a strategy via constructor injection and delegates behaviour to it. This eliminates switch/if-else chains that select algorithms (replacing switch smell with polymorphism), makes algorithms independently testable, and follows Open/Closed Principle — new strategies are added without modifying the context. Classic PHP examples: payment processors, sorting algorithms, and report formatters.",
    "aliases": [
        "strategy",
        "policy pattern",
        "interchangeable algorithm"
    ],
    "tags": [
        "general",
        "design-pattern",
        "oop",
        "behavioural"
    ],
    "misconception": "Strategy and State patterns are interchangeable since both swap behaviour. Strategy objects are chosen by the client and remain stable. State objects transition themselves — the object changes its own behaviour based on internal state transitions without the client selecting which strategy to use.",
    "why_it_matters": "The Strategy pattern defines a family of interchangeable algorithms — swapping behaviour at runtime without conditionals, making it easy to add new strategies without modifying existing code.",
    "common_mistakes": [
        "Strategies that depend on the context object — they should be independent algorithms.",
        "Too many strategies for trivial variations — a simple parameter is cleaner than a strategy class.",
        "Not using interfaces for strategies — callers become coupled to concrete strategy types.",
        "Forgetting to inject the strategy — instantiating it inside the context defeats the purpose."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "switch_smell",
        "open_closed_principle",
        "dependency_injection"
    ],
    "prerequisites": [
        "interfaces",
        "dependency_injection",
        "open_closed_principle"
    ],
    "refs": [
        "https://refactoring.guru/design-patterns/strategy"
    ],
    "bad_code": "function sortUsers(array $users, string $by): array {\n    if ($by === 'name') {\n        usort($users, fn($a,$b) => strcmp($a->name, $b->name));\n    } elseif ($by === 'age') {\n        usort($users, fn($a,$b) => $a->age <=> $b->age);\n    } elseif ($by === 'score') {\n        usort($users, fn($a,$b) => $b->score <=> $a->score);\n    } // must edit this function for every new sort\n    return $users;\n}",
    "good_code": "interface SortStrategy {\n    public function compare(User $a, User $b): int;\n}\n\nclass SortByName  implements SortStrategy { public function compare(User $a, User $b): int { return strcmp($a->name, $b->name); } }\nclass SortByAge   implements SortStrategy { public function compare(User $a, User $b): int { return $a->age <=> $b->age; } }\nclass SortByScore implements SortStrategy { public function compare(User $a, User $b): int { return $b->score <=> $a->score; } }\n\nfunction sortUsers(array $users, SortStrategy $strategy): array {\n    usort($users, $strategy->compare(...));\n    return $users;\n}",
    "quick_fix": "Extract the varying algorithm into an interface, create one class per strategy, inject the chosen strategy — eliminates the switch/if-else that changes every time a new algorithm is added",
    "severity": "low",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/strategy_pattern",
        "html_url": "https://codeclaritylab.com/glossary/strategy_pattern",
        "json_url": "https://codeclaritylab.com/glossary/strategy_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": "[Strategy Pattern](https://codeclaritylab.com/glossary/strategy_pattern) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/strategy_pattern"
            }
        }
    }
}