A shared vocabulary for object-oriented design
The 1994 book Design Patterns by Gamma, Helm, Johnson and Vlissides — the Gang of Four — catalogued 23 reusable solutions to recurring design problems. This reference lists all 23, grouped by purpose, with each pattern’s intent and a concrete use case so you can recognise where one fits. Search by keyword or filter by group.
The three pattern families
The patterns split into three families by what they manage:
Creational (5) → how objects are created
Abstract Factory, Builder, Factory Method, Prototype, Singleton
Structural (7) → how objects are composed
Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy
Behavioural (11) → how objects communicate and share responsibility
Chain of Responsibility, Command, Interpreter, Iterator, Mediator,
Memento, Observer, State, Strategy, Template Method, Visitor
Each pattern names a problem and a tested solution. Saying “use an Adapter here” or “this needs an Observer” conveys a whole design decision in two words — that shared vocabulary is as valuable as any specific code structure.
The most commonly confused pairs
Several patterns share surface-level similarities but address different concerns. Knowing the distinctions stops you reaching for the wrong one.
| Confused pair | The difference |
|---|---|
| Decorator vs Proxy | Decorator adds new behaviour; Proxy controls access to an existing object (lazy init, caching, access rights). |
| Strategy vs State | Strategy lets a client pick an interchangeable algorithm. State changes behaviour as the object itself transitions through stages. |
| Adapter vs Facade | Adapter makes two incompatible interfaces work together. Facade hides a complex subsystem behind a simpler one. |
| Factory Method vs Abstract Factory | Factory Method delegates one product’s creation to a subclass. Abstract Factory produces families of related objects. |
When to apply a pattern — and when not to
Patterns solve recognised recurring problems. Reach for one when you see its specific trigger: adding behaviour without editing a class (Decorator), wrapping a legacy API your new code cannot use (Adapter), broadcasting state changes to multiple dependents (Observer). Do not apply them speculatively; a pattern applied to a problem it does not solve adds indirection and confusion rather than clarity.
Some patterns that once required boilerplate are now built into modern languages: Iterator is a native protocol in Python and JavaScript, Observer is the event model in every UI framework, and first-class functions often replace a full Strategy or Command class with a single closure. Use the language feature where it exists and reach for the formal pattern when the problem genuinely warrants it.
Tips and notes
- Favour composition (Strategy, Decorator) over deep inheritance hierarchies.
- Singleton introduces global mutable state, making tests and concurrent code harder — use dependency injection instead except for truly unique resources.
- Flyweight is specifically an optimisation for memory when many identical objects are created; do not reach for it before profiling.