{
    "slug": "abstract_factory",
    "term": "Abstract Factory Pattern",
    "category": "quality",
    "difficulty": "intermediate",
    "short": "Creates families of related objects ensuring they are used together consistently without mixing implementations.",
    "long": "The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. Each concrete factory produces a consistent set of products (e.g., StripeGateway, StripeRequest, StripeResponse). This ensures that objects designed to work together are never mixed with incompatible ones. It is commonly used when systems must support multiple interchangeable configurations (e.g., payment providers, UI themes, database drivers). Unlike Factory Method, which creates a single product, Abstract Factory guarantees consistency across a full product family.",
    "aliases": [
        "abstract factory",
        "family factory"
    ],
    "tags": [
        "patterns",
        "oop",
        "design",
        "creational"
    ],
    "misconception": "Abstract Factory and Factory Method are interchangeable. Factory Method creates a single product, while Abstract Factory ensures a consistent family of related products is created together.",
    "why_it_matters": "Without Abstract Factory, systems can accidentally mix incompatible objects from different providers — these errors often compile but fail at runtime and are hard to trace.",
    "common_mistakes": [
        "Using Abstract Factory when only one product varies — adds unnecessary complexity.",
        "Creating factories that return unrelated objects — defeats the purpose of product families.",
        "Exposing concrete factories directly instead of injecting abstractions.",
        "Mixing factory-created objects with manually instantiated ones."
    ],
    "when_to_use": [
        "Multiple related objects must always be used together.",
        "System must support interchangeable product families (e.g., providers, themes).",
        "You want to enforce compatibility between created objects.",
        "Configuration should swap entire implementations, not individual classes."
    ],
    "avoid_when": [
        "Only one product type varies — use Factory Method instead.",
        "Products are independent and do not need to be used together.",
        "System has a single fixed implementation with no variation.",
        "The abstraction adds more complexity than the variation justifies."
    ],
    "related": [
        "factory_pattern",
        "builder_pattern",
        "dependency_injection"
    ],
    "prerequisites": [],
    "refs": [
        "https://refactoring.guru/design-patterns/abstract-factory"
    ],
    "bad_code": "// ❌ Mixing incompatible product families\n$gateway = new StripeGateway();\n$request = new BraintreePaymentRequest(); // runtime mismatch",
    "good_code": "interface PaymentFactory {\n    public function createGateway(): GatewayInterface;\n    public function createRequest(Money $amount): RequestInterface;\n    public function createResponse(array $data): ResponseInterface;\n}\n\nfinal class StripeFactory implements PaymentFactory {\n    public function createGateway(): GatewayInterface {\n        return new StripeGateway();\n    }\n\n    public function createRequest(Money $amount): RequestInterface {\n        return new StripeRequest($amount);\n    }\n\n    public function createResponse(array $data): ResponseInterface {\n        return new StripeResponse($data);\n    }\n}\n\n// Usage\nfunction processPayment(PaymentFactory $factory, Money $amount) {\n    $gateway = $factory->createGateway();\n    $request = $factory->createRequest($amount);\n\n    $rawResponse = $gateway->send($request);\n\n    return $factory->createResponse($rawResponse);\n}",
    "example_note": "All objects are created via the same factory, guaranteeing they belong to the same compatible family.",
    "quick_fix": "If multiple related objects must always be used together, introduce an Abstract Factory and inject it instead of instantiating objects directly.",
    "severity": "low",
    "effort": "medium",
    "created": "2026-03-16",
    "updated": "2026-03-27",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/abstract_factory",
        "html_url": "https://codeclaritylab.com/glossary/abstract_factory",
        "json_url": "https://codeclaritylab.com/glossary/abstract_factory.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": "[Abstract Factory Pattern](https://codeclaritylab.com/glossary/abstract_factory) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/abstract_factory"
            }
        }
    }
}