{
    "slug": "factory_pattern",
    "term": "Factory Pattern",
    "category": "general",
    "difficulty": "intermediate",
    "short": "Delegates object creation to a dedicated factory, decoupling the creator from the created class and allowing subclass instantiation.",
    "long": "Factory patterns (Factory Method, Abstract Factory, Static Factory) abstract object creation logic from consuming code. Instead of new ConcreteClass(), call a factory that decides which concrete class to instantiate based on parameters or configuration. This follows Dependency Inversion (depend on the interface returned, not the concrete class), makes construction logic testable, and makes swapping implementations easy. In PHP, static factory methods on value objects (Money::fromFloat(9.99, 'GBP')) are a lightweight pattern that centralises validation and construction.",
    "aliases": [
        "factory method",
        "abstract factory",
        "static factory"
    ],
    "tags": [
        "general",
        "design-pattern",
        "oop",
        "creational"
    ],
    "misconception": "Factory Method and Abstract Factory are just variations of the same pattern. Factory Method defines an interface for creating one object, letting subclasses decide the class. Abstract Factory creates families of related objects. They solve different scoping problems — single object vs coordinated object families.",
    "why_it_matters": "The Factory pattern centralises object creation — callers don't need to know which concrete class to instantiate, making it easy to change implementations or add new ones without touching call sites.",
    "common_mistakes": [
        "Factories that return concrete types instead of interfaces — callers are still coupled to the implementation.",
        "Static factory methods that cannot be overridden in subclasses — use instance factories for flexibility.",
        "Over-using factories for simple objects that could just use new — factories are for creation that involves logic.",
        "Factory classes with dozens of create methods — a sign the factory has grown into a god object."
    ],
    "when_to_use": [
        "The concrete class to instantiate is determined at runtime based on configuration or input.",
        "Object creation involves complex setup, dependency resolution, or conditional branching.",
        "You want to enforce that objects are always created in a valid state with required dependencies.",
        "Testing — factories make it easy to swap real implementations for test doubles."
    ],
    "avoid_when": [
        "You only ever create one type of object and the creation logic is trivial — a factory adds indirection with no benefit.",
        "The factory itself becomes a god object that knows about every concrete class — defeats the purpose of abstraction.",
        "Simple value objects with no dependencies — new Point(1, 2) is clearer than PointFactory::create(1, 2)."
    ],
    "related": [
        "dependency_injection",
        "value_object",
        "singleton"
    ],
    "prerequisites": [
        "dependency_injection",
        "interfaces",
        "single_responsibility"
    ],
    "refs": [
        "https://refactoring.guru/design-patterns/factory-method"
    ],
    "bad_code": "// Object creation scattered across codebase — hard to change:\n$mailer = new SmtpMailer('smtp.example.com', 587, 'user', 'pass');\n// Same constructor call in 12 places — change SMTP provider = 12 edits\n\n// Factory — centralised:\nclass MailerFactory {\n    public function create(): MailerInterface {\n        return new SmtpMailer(config('mail.host'), config('mail.port'));\n    }\n}",
    "good_code": "interface Logger {\n    public function log(string $msg): void;\n}\n\nclass LoggerFactory {\n    public static function create(string $driver): Logger {\n        return match($driver) {\n            'file'     => new FileLogger(),\n            'database' => new DatabaseLogger(),\n            'null'     => new NullLogger(),\n            default    => throw new \\InvalidArgumentException(\"Unknown driver: $driver\"),\n        };\n    }\n}\n\n$logger = LoggerFactory::create($_ENV['LOG_DRIVER'] ?? 'file');",
    "quick_fix": "Extract object creation logic into a factory when construction is complex, involves conditions, or needs to be mocked in tests — factories keep the calling code clean of instantiation detail",
    "severity": "low",
    "effort": "low",
    "created": "2026-03-15",
    "updated": "2026-03-25",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/factory_pattern",
        "html_url": "https://codeclaritylab.com/glossary/factory_pattern",
        "json_url": "https://codeclaritylab.com/glossary/factory_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": "[Factory Pattern](https://codeclaritylab.com/glossary/factory_pattern) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/factory_pattern"
            }
        }
    }
}