The Gang of Four book (Gamma, Helm, Johnson, Vlissides, 1994) catalogued 23 reusable solutions to recurring object-oriented design problems. Knowing them gives you a shared vocabulary and a head start on structuring code. This reference lists every pattern with its intent and the situation it addresses.
How it works
The 23 patterns split into three families:
- Creational (5) — control object creation: Abstract Factory, Builder, Factory Method, Prototype, Singleton.
- Structural (7) — compose objects and classes: Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy.
- Behavioral (11) — manage algorithms and responsibilities: Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor.
For each, read the intent (what it achieves) and the when note (the problem that justifies it). Match the problem first, then apply the pattern.
Example
You need to add logging and compression to a data stream without subclassing
every stream type for every combination. That is the Decorator problem: wrap
the stream in a LoggingStream, then wrap that in a CompressingStream, each
adding one responsibility and forwarding the rest. The combinations multiply at
runtime, not through a class explosion.
Notes
- Patterns describe relationships and intent, not specific code — the same pattern looks different across languages.
- Several patterns overlap by structure but differ by intent (Adapter vs Decorator vs Proxy all wrap an object).
- Modern languages bake some patterns in: first-class functions make Strategy and Command lightweight, and iterators are built into most standard libraries.
- Over-applying patterns is a smell of its own — see the SOLID, KISS and YAGNI principles for the counterweight.
Common confusion pairs
Adapter vs Decorator vs Proxy
All three wrap a target object, which is why they are routinely conflated:
- Adapter changes the interface — it lets a client use an incompatible class by translating calls. The classic example is wrapping a legacy API so it matches a new interface the rest of the codebase expects.
- Decorator keeps the same interface and adds behaviour — wrapping a
Beveragein aMilkDecoratorstill gives you aBeverage, just with extra cost and description. - Proxy keeps the same interface and controls access — a remote proxy forwards calls across a network, a virtual proxy delays expensive construction, a protection proxy checks permissions.
Strategy vs Template Method
Both define a family of algorithms, but the inversion of control differs. Strategy injects the algorithm from outside (composition) — the client passes a sorting strategy to a Sorter that calls it. Template Method defines the skeleton in a base class and lets subclasses fill in specific steps (inheritance) — the base class calls doStep() which the subclass overrides.
Observer vs Mediator
Both handle loose coupling between objects. Observer is one-to-many: a subject notifies many subscribers when its state changes, and subscribers react independently. Mediator centralises coordination: components talk to the mediator, not to each other, which makes complex many-to-many communication manageable but concentrates logic.
Which patterns appear most in modern codebases
Despite the book’s age, most of the patterns survive in modern frameworks, often by a different name:
| Pattern | Where you see it |
|---|---|
| Observer | Event emitters, reactive streams, Redux actions |
| Strategy | Sorting comparators, pluggable auth methods |
| Decorator | Express/Koa middleware, Python @decorator |
| Factory Method | ORM model creation, DI containers |
| Singleton | Module-level exports (used carefully) |
| Command | Undo stacks, job queues, CQRS write side |
| Iterator | for...of, generators, cursor pagination |
| Facade | Service layers hiding a complex subsystem |
The anti-pattern version of each usually involves reaching for the pattern when simpler code would do — a Singleton for a stateless utility, or a full Command stack for a feature with no undo requirement. Apply the pattern when the problem it solves is genuinely present.