Design Patterns

Design Patterns Overview

A design pattern is a named, reusable solution to a recurring object-oriented design problem — not a library to import, but a shape to recognize and adapt. The value is the shared vocabulary as much as the code.
  • A pattern has four parts: a name, the problem it addresses, the solution shape (a structure of classes/objects and their relationships), and the consequences (trade-offs of using it)
  • The Gang of Four (GoF) catalog groups 23 classic patterns into three families: creational (object creation), structural (object composition), behavioral (object interaction and responsibility)
  • Patterns codify "favor composition over inheritance" and "program to an interface, not an implementation" — most patterns are specific applications of these two principles
  • A pattern is a starting point, not a mandate — applying one where the problem doesn't call for it adds indirection and complexity for no benefit (Anti Patterns And Pattern Misuse)
  • Recognizing a pattern in someone else's code is often more valuable day-to-day than writing one from scratch — it tells you what to expect from the design

The historical context matters for understanding why the catalog looks the way it does: it was written against Smalltalk and C++ in the early 1990s, languages without lambdas, without first-class functions, and (in C++'s case) without garbage collection. Several GoF patterns exist specifically to work around the absence of a language feature — Strategy and Command are largely replaced by a lambda in modern Java for the simple cases, and Iterator is built into every language with a for-each loop. The patterns aren't obsolete, but a fair number of their simplest use cases now have lighter-weight solutions.

The three GoF families, at a glance
FamilyConcerned withExamples
Creationalhow objects get created, hiding the concrete class from the callerFactory Method, Builder, Singleton (Creational Patterns)
Structuralhow classes and objects are composed into larger structuresAdapter, Decorator, Facade (Structural Patterns)
Behavioralhow objects communicate and distribute responsibilityStrategy, Observer, Command (Behavioral Patterns I)
The two principles nearly every pattern is an application of
// "Program to an interface, not an implementation":
List<String> names = new ArrayList<>();     // caller depends on List, not ArrayList

// "Favor composition over inheritance":
class Car {
    private final Engine engine;             // Car HAS-A Engine — swap engines freely
    Car(Engine engine) { this.engine = engine; }
}
// vs. a rigid class hierarchy: class ElectricCar extends Car { ... } — locked in at compile time
Sources
  • Head First Design Patterns (2nd ed.)Ch. 1 — Intro to Design Patterns