Skip to content
1 min read

Creational Design Patterns

Creational patterns abstract the instantiation process — they make a system independent of how its objects are created, composed, and represented.


%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '13px', 'fontFamily': 'Inter, -apple-system, sans-serif'}, 'flowchart': {'nodeSpacing': 30, 'rankSpacing': 50, 'padding': 12, 'curve': 'basis'}, 'sequence': {'actorMargin': 60, 'messageMargin': 40}, 'class': {'padding': 12}}}%%
flowchart LR
    C["🟡 Creational"] -->|"asks"| Q["❓ How to create?"]
    Q -->|"goal"| G1["✅ Hide logic"] --> G2["✅ Flexible"] --> G3["✅ Decoupled"]

    style C fill:#FFF3E0,stroke:#E65100,stroke-width:2px,color:#000
    style Q fill:#FEF3C7,stroke:#D97706,color:#000
    style G1 fill:#E8F5E9,stroke:#2E7D32,color:#000
    style G2 fill:#E8F5E9,stroke:#2E7D32,color:#000
    style G3 fill:#E8F5E9,stroke:#2E7D32,color:#000

Why Creational Patterns?

As systems grow, hardcoding object creation (new ConcreteClass()) everywhere leads to:

  • Tight coupling — changing one class means modifying dozens of files
  • Inflexibility — can't swap implementations without rewriting code
  • Duplication — creation logic scattered and repeated

Creational patterns solve this by encapsulating which classes get instantiated and hiding how instances are assembled.


The 5 Creational Patterns

# Pattern When to Use Key Idea
1 Singleton Need exactly ONE instance Private constructor + static access
2 Factory Method Let subclasses decide what to create Interface for creation, subclass implements
3 Abstract Factory Need families of related objects Factory of factories
4 Builder Complex objects with many options Step-by-step construction
5 Prototype Expensive creation, clone instead Copy existing objects

Choosing the Right Pattern

%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '13px', 'fontFamily': 'Inter, -apple-system, sans-serif'}, 'flowchart': {'nodeSpacing': 30, 'rankSpacing': 50, 'padding': 12, 'curve': 'basis'}, 'sequence': {'actorMargin': 60, 'messageMargin': 40}, 'class': {'padding': 12}}}%%
flowchart LR
    Start{"🤔 How to create?"}
    Start -->|"one instance?"| Sing(["🎯 Singleton"])
    Start -->|"pick type at runtime?"| Fact(["🏭 Factory"])
    Fact -->|"whole family?"| AF(["🏗️ Abstract Factory"])
    Start -->|"many options?"| Build(["🔨 Builder"])
    Start -->|"expensive? clone!"| Proto(["🧬 Prototype"])

    style Start fill:#FEF3C7,stroke:#D97706,stroke-width:2px,color:#000
    style Sing fill:#E3F2FD,stroke:#1565C0,color:#000
    style Fact fill:#E8F5E9,stroke:#2E7D32,color:#000
    style AF fill:#FFF3E0,stroke:#E65100,color:#000
    style Build fill:#FFF8E1,stroke:#F9A825,color:#000
    style Proto fill:#FCE4EC,stroke:#C62828,color:#000

Key Principle

All creational patterns share one goal: program to an interface, not an implementation. The client never needs to know the exact class being instantiated — only the contract it fulfills.