Reference
Design Patterns
A pattern catalog is easy to find. What is harder to find is an explanation of why each pattern exists: what pressure in real code produced it, and what it costs you to adopt. That is the part I care about, so every page here ends with it.
43 of 43 written · all 23 Gang of Four patterns, the foundations underneath them, and the ones that took over after 1995.
Creational
5/5Patterns about how objects get made: deferring the choice of concrete class, controlling how many exist, or separating construction from representation.
Create whole families of related objects without naming their concrete classes.
Assemble a complex object step by step so one process can produce several representations.
Let a subclass decide which class to instantiate.
Create new objects by copying an existing configured instance.
Guarantee a class has exactly one instance, reachable from anywhere.
Structural
7/7Patterns about how classes and objects are composed into larger structures. Several are now built directly into modern languages.
Translate one interface into another so two finished classes can work together.
Split an abstraction from its implementation so the two can vary independently.
Treat a single object and a whole tree of objects through one interface.
Add behavior to one object at runtime without touching its class or its interface.
Put one simple door in front of a complicated subsystem.
Share the identical parts of many small objects instead of duplicating them.
Stand in for another object to control when and how it is reached.
Behavioral
11/11Patterns about how responsibility is assigned and how objects talk to each other, covering the algorithms and the flow of control.
Pass a request along a line of handlers until one of them deals with it.
Turn a request into an object you can queue, log, undo, or send over a wire.
Represent a small language as a tree of objects that evaluate themselves.
Walk a collection without exposing how it stores its elements.
Route all communication through one hub so components stop knowing about each other.
Capture an object's state so it can be restored later, without breaking encapsulation.
Let many objects react automatically when one object changes.
Give each state its own class so the object appears to change class as it changes state.
Make an algorithm a swappable object chosen at runtime.
Fix the skeleton of an algorithm in the base class and let subclasses fill in the steps.
Add new operations to a class hierarchy without editing the classes in it.
Foundations
5/5Ideas that sit underneath the catalog. Some are too fundamental to call patterns, some are patterns the Gang of Four left out, and one is just my own way of telling the structural patterns apart.
How the structural patterns differ, told entirely through what each one does to an interface.
Hide state behind an accessor boundary to limit what can change it, and when.
Treat a cluster of objects as one unit with a single entry point and one consistency boundary.
Build a frame of modules so functionality can be added later without reopening the core.
Chain narrow processing stages together with a data stream between them.
Modern Practice
10/10Patterns that dominate working code today but sit outside the 1995 catalog. They were either invented after it, or considered too obvious to write down at the time.
Hand a class its collaborators instead of letting it construct or find them.
Supply a do-nothing implementation so callers never have to test for absence.
Recycle expensive objects instead of creating and destroying them.
Put a collection-shaped interface in front of storage so the domain never sees the database.
Forward work to a held object rather than inheriting the ability to do it.
Tag a type with an empty interface so other code can ask what it is allowed to do.
Group related things behind one deliberately narrow public surface.
Let clients ask an object at runtime for an interface it might also support.
Defer the cost of getting data until something actually asks for it.
One instance per key, instead of one instance overall.
Ownership and Lifetimes
5/5Patterns that came out of Rust, where the compiler tracks who owns a value and how long it lives. They answer questions the 1995 catalog never asked, because it assumed the programmer would get resource lifetime right by hand. Most of them have older relatives in C and C++.
Allocate many objects with one lifetime, and release them all at once.
Wrap a value in a distinct type so the compiler stops treating inches and degrees as interchangeable.
Put the state machine in the type system, so an illegal transition fails to compile.
Tie release to scope, so it still happens on the error path nobody tested.
Mutate through a shared reference by moving the borrow check from compile time to run time.
Sources and further reading are collected in the bibliography.