{
    "slug": "adapter_pattern",
    "term": "Adapter Pattern",
    "category": "general",
    "difficulty": "intermediate",
    "short": "Converts the interface of a class into another interface clients expect, allowing incompatible interfaces to work together.",
    "long": "The Adapter (Wrapper) pattern bridges the gap between an existing class with an incompatible interface and the interface expected by client code. It wraps the adaptee and implements the target interface, translating calls. This is essential when integrating third-party libraries or legacy code without modifying either. In PHP, adapting a payment gateway SDK to a standardised PaymentGatewayInterface, or wrapping a legacy Logger to a PSR-3 LoggerInterface, are common use cases. Adapters also facilitate testability by wrapping external dependencies.",
    "aliases": [
        "adapter",
        "wrapper pattern",
        "object adapter"
    ],
    "tags": [
        "general",
        "design-pattern",
        "oop",
        "structural"
    ],
    "misconception": "Adapter and Facade patterns are interchangeable. Facade simplifies a complex subsystem behind a single interface. Adapter makes an incompatible interface compatible with what a client expects — different problems, different solutions.",
    "why_it_matters": "The Adapter pattern wraps an incompatible interface to match an expected one — enabling integration of third-party code or legacy systems without modifying either side.",
    "common_mistakes": [
        "Adapters that transform data as well as interface — separate the data mapping from the interface adaptation.",
        "Not programming to the target interface — the adapter is only useful if callers depend on the interface, not the adapter.",
        "Creating an adapter for every third-party class rather than a single adapter for the library's entry point.",
        "Adapters that leak the underlying library's exceptions — wrap them in domain exceptions."
    ],
    "when_to_use": [
        "Integrating a third-party library whose interface does not match your domain's expectations.",
        "Making legacy code work with a new interface without modifying the legacy code.",
        "Enabling multiple implementations behind a single interface for swappability.",
        "Wrapping external APIs so your domain is insulated from their changes."
    ],
    "avoid_when": [
        "The interface mismatch is trivial — a one-line wrapper does not need a full adapter class.",
        "You control both interfaces and can change them — adapt the source instead of wrapping it.",
        "Overusing adapters hides poor API design that should be fixed at the source."
    ],
    "related": [
        "dependency_injection",
        "interfaces",
        "strangler_fig"
    ],
    "prerequisites": [
        "interfaces",
        "dependency_injection",
        "hexagonal_architecture"
    ],
    "refs": [
        "https://refactoring.guru/design-patterns/adapter"
    ],
    "bad_code": "// Direct dependency on third-party Stripe library everywhere:\nclass PaymentService {\n    public function charge(float $amount): void {\n        \\Stripe\\Charge::create(['amount' => $amount * 100, 'currency' => 'usd']);\n        // Stripe leak throughout codebase — impossible to swap\n    }\n}\n// Better: StripePaymentAdapter implements PaymentGatewayInterface",
    "good_code": "// Your app expects this interface\ninterface Logger {\n    public function log(string $level, string $message): void;\n}\n\n// Third-party library uses a different API\nclass MonologAdapter implements Logger {\n    public function __construct(private \\Monolog\\Logger $monolog) {}\n\n    public function log(string $level, string $message): void {\n        $this->monolog->$level($message); // adapts your interface to Monolog's\n    }\n}\n\n// Your code depends on Logger — not Monolog directly\n$logger = new MonologAdapter(new \\Monolog\\Logger('app'));\n$service = new OrderService($logger);",
    "quick_fix": "When integrating a third-party library that doesn't match your domain interface, create an adapter class that wraps the library and implements your interface",
    "severity": "low",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-25",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/adapter_pattern",
        "html_url": "https://codeclaritylab.com/glossary/adapter_pattern",
        "json_url": "https://codeclaritylab.com/glossary/adapter_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": "[Adapter Pattern](https://codeclaritylab.com/glossary/adapter_pattern) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/adapter_pattern"
            }
        }
    }
}