| Problem | Pattern | Category |
|---|---|---|
| Need exactly one global instance | Singleton | Creational |
| Create objects without specifying class | Factory | Creational |
| Complex object construction | Builder | Creational |
| Incompatible interface | Adapter | Structural |
| Add behavior without subclassing | Decorator | Structural |
| Simplify complex subsystem | Facade | Structural |
| Notify multiple objects of state change | Observer | Behavioral |
| Swap algorithms at runtime | Strategy | Behavioral |
| Encapsulate actions with undo support | Command | Behavioral |
| Pass request through handler chain | Chain of Responsibility | Behavioral |
| Coordinate async producers & consumers | Producer/Consumer | Concurrency |
| Protect calls to unreliable services | Circuit Breaker | Concurrency |
START → Do you need to create objects?
│
├─ YES → Is construction complex (many optional params)?
│ ├─ YES → Builder
│ └─ NO → Do you need to decouple creation from usage?
│ ├─ YES → Factory
│ └─ NO → Do you need exactly one instance?
│ ├─ YES → Singleton
│ └─ NO → Plain constructor is fine
│
└─ NO → Do you need to add behavior?
├─ YES → Is it cross-cutting (logging, retry, caching)?
│ ├─ YES → Decorator
│ └─ NO → Do you need to swap behavior at runtime?
│ ├─ YES → Strategy
│ └─ NO → Standard subclassing
│
└─ NO → Do you need to handle events/actions?
├─ YES → Do multiple listeners need notification?
│ ├─ YES → Observer
│ └─ NO → Do you need undo/redo?
│ ├─ YES → Command
│ └─ NO → Do handlers form a pipeline?
│ ├─ YES → Chain of Responsibility
│ └─ NO → Direct method call
│
└─ NO → Is this about resilience or async work?
├─ Async pipeline → Producer/Consumer
├─ Unreliable service → Circuit Breaker
└─ Complex subsystem → Facade / Adapter
Patterns work well together. Common pairings:
1. Singleton overuse — Use dependency injection instead when possible.
Singletons make testing harder and hide dependencies.
2. Factory for one type — If you only ever create one class, a factory
adds complexity without benefit.
3. Deep decorator stacks — More than 3-4 decorators becomes hard to
debug. Consider a pipeline or middleware approach instead.
4. Observer memory leaks — Always unsubscribe when listeners are
destroyed. Use weak references for long-lived event buses.
5. God Facade — A facade should simplify, not become a dumping ground.
If it grows beyond ~10 methods, split into multiple facades.
"A pattern is a solution to a problem in a context. No problem, no pattern."