{
    "slug": "state_pattern",
    "term": "State Pattern",
    "category": "quality",
    "difficulty": "intermediate",
    "short": "Encapsulates the varying behaviour of an object based on its internal state into separate state objects, eliminating state-based conditionals.",
    "long": "The State pattern models an object whose behaviour changes based on its current state by delegating to a State object. Each concrete state implements the same interface, and the context simply forwards calls to the current state. Transitioning between states is handled by the state objects themselves or the context. This replaces sprawling if/switch chains on a status field with polymorphism, follows Open/Closed Principle (new states = new classes, not new branches), and localises state-specific behaviour. In PHP, common examples include order workflows, connection states, and document approval processes.",
    "aliases": [
        "state machine pattern",
        "finite state machine",
        "state design pattern"
    ],
    "tags": [
        "design-pattern",
        "oop",
        "behavioural"
    ],
    "misconception": "A switch statement on a status field is equivalent to the state pattern. A switch scatters state-specific logic across the codebase — the state pattern encapsulates each state's behaviour in its own class, making new states addable without modifying existing code.",
    "why_it_matters": "The State pattern replaces complex conditionals checking internal state with polymorphism — each state is a class, transitions are explicit, and adding a new state does not require modifying existing states.",
    "common_mistakes": [
        "Implementing state as a string or integer flag with switch statements — the anti-pattern the State pattern replaces.",
        "State classes with too much business logic — they should manage transitions and delegate business logic to the context.",
        "Not preventing invalid transitions — every state should only allow transitions to valid next states.",
        "Overusing State pattern for objects with 2-3 states where a simple boolean or enum suffices."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "strategy_pattern",
        "switch_smell",
        "open_closed_principle",
        "enums"
    ],
    "prerequisites": [
        "interfaces",
        "strategy_pattern",
        "enums"
    ],
    "refs": [
        "https://refactoring.guru/design-patterns/state"
    ],
    "bad_code": "// Switch on status string — grows with every new state:\nfunction handleOrder(Order $o): void {\n    switch ($o->status) {\n        case 'pending': /* ... */ break;\n        case 'paid': /* ... */ break;\n        case 'shipped': /* ... */ break;\n        // Each new status requires modifying this switch\n    }\n}",
    "good_code": "interface OrderState {\n    public function pay(Order $order): void;\n    public function ship(Order $order): void;\n    public function cancel(Order $order): void;\n}\n\nclass PendingState implements OrderState {\n    public function pay(Order $o): void    { $o->setState(new PaidState()); }\n    public function ship(Order $o): void   { throw new \\LogicException('Pay first'); }\n    public function cancel(Order $o): void { $o->setState(new CancelledState()); }\n}\n\nclass PaidState implements OrderState {\n    public function pay(Order $o): void    { throw new \\LogicException('Already paid'); }\n    public function ship(Order $o): void   { $o->setState(new ShippedState()); }\n    public function cancel(Order $o): void { $o->setState(new RefundingState()); }\n}",
    "quick_fix": "Replace switch-on-status with a State object per state — each state implements the same interface but with state-specific behaviour, and transitions are handled by the states themselves",
    "severity": "low",
    "effort": "high",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/state_pattern",
        "html_url": "https://codeclaritylab.com/glossary/state_pattern",
        "json_url": "https://codeclaritylab.com/glossary/state_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": "[State Pattern](https://codeclaritylab.com/glossary/state_pattern) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/state_pattern"
            }
        }
    }
}