From buildings to software
In the 1970s, architect Christopher Alexander wrote A Pattern Language, describing recurring solutions in physical architecture — how a window seat, a courtyard, or a building entrance should be shaped. His insight: good design isn't random; the same problems recur and have time-tested solutions worth naming.
In 1994, four software engineers — Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides — applied that idea to object-oriented software in the book Design Patterns: Elements of Reusable Object-Oriented Software. The book was so influential that the authors became known simply as the "Gang of Four" (GoF), and the 23 patterns they catalogued are still the canonical set taught everywhere.
When an interviewer or a senior engineer says "GoF patterns," they mean these 23. Knowing the catalog by family is enough to navigate almost any design conversation.
Two ways the GoF classified patterns
The book sorts patterns along two axes:
- Purpose — what the pattern does: creational, structural, or behavioral. This is the split we'll use throughout the course.
- Scope — whether the pattern applies mainly to classes (relationships fixed at compile time, via inheritance) or objects (relationships set at runtime, via composition). Most patterns are object-scoped — composition is more flexible than inheritance.
The full catalog
Here is the map you'll fill in module by module. Don't memorize it — just know it exists and roughly what each family is for.
| Creational | Structural | Behavioral |
|---|---|---|
| Singleton | Adapter | Strategy |
| Factory Method | Decorator | Observer |
| Abstract Factory | Facade | Command |
| Builder | Composite | State |
| Prototype | Proxy | Template Method |
| Bridge | Iterator | |
| Flyweight | Chain of Responsibility | |
| Mediator | ||
| Memento | ||
| Visitor | ||
| Interpreter |
Class scope vs object scope
A quick taste of the "scope" axis. A class-scoped relationship is fixed by inheritance; an object-scoped one is wired at runtime by holding a reference. The GoF — and modern practice — favor the latter ("favor composition over inheritance"):
// CLASS scope: behavior fixed at compile time via inheritance
class Report extends PdfExporter { } // a Report IS-A PdfExporter, forever
// OBJECT scope: behavior chosen at runtime via composition
class Report {
private Exporter exporter; // a Report HAS-A Exporter
Report(Exporter exporter) { this.exporter = exporter; }
void export() { exporter.export(this); } // swap PDF/HTML/JSON at runtime
}The composed version can change exporters without a new subclass — which is exactly why most patterns lean on object scope.
The book is from 1994 and its examples are in C++ and Smalltalk. The ideas are timeless, but some patterns (like Singleton) are now used more cautiously, and a few feel less necessary in modern languages. We'll flag this each time it matters.
Patterns came from architecture (Alexander) and were brought to software by the Gang of Four in 1994. There are 23 classic patterns, classified by purpose (creational / structural / behavioral) and by scope (class vs object). Composition-based, object-scoped patterns dominate because they're more flexible than inheritance.