The Gang of Four catalog names 23 recurring object-oriented design problems and the collaborations that address them. A pattern communicates intent and consequences. It is not a ready-made class diagram. Strategy says that an algorithm varies behind a stable contract, while Observer says that an unknown set of dependents receives notifications. The name is useful only when that pressure exists in the code.
The catalog groups patterns by what varies. Creational patterns move construction decisions, structural patterns compose objects and interfaces, and behavioral patterns assign work or communication. The categories help with recall, but intent decides the pattern.
Choose a Pattern by Intent and Cost
Pattern selection starts from the pressure in the code. The smallest pattern that makes a real variation or responsibility boundary explicit is the candidate, and the condition that would justify deleting it is kept with that decision.
| Pressure | Candidate | What it buys | What it costs | Reject it when |
|---|---|---|---|---|
| Construction selects among related product families | Software Architecture/Patterns/Design Patterns/Creational/Abstract Factory | Keeps compatible products and construction policy together | Each new family adds a concrete factory; each new product kind adds a product interface and an abstract-factory operation that every concrete factory must implement | There is one concrete family |
| Construction has many ordered or optional inputs | Software Architecture/Patterns/Design Patterns/Creational/Builder | Names construction steps and protects invariants | Extra builder type and duplicated API surface | A constructor or options record stays readable |
| Existing interface does not match a consumer | Software Architecture/Patterns/Design Patterns/Structural/Adapter | Localizes translation at one boundary | Another abstraction to test and maintain | Both sides are controlled and their contracts can be aligned directly |
| Add behavior around one object without subclass combinations | Software Architecture/Patterns/Design Patterns/Structural/Decorator | Composes responsibilities at runtime | Nested wrappers obscure execution order | One direct implementation has no meaningful variants |
| Choose one interchangeable algorithm | Software Architecture/Patterns/Design Patterns/Behavioral/Strategy | Makes policy selection explicit and testable | More types or delegates | A small conditional is stable and clearer |
| Notify unknown dependents about state changes | Software Architecture/Patterns/Design Patterns/Behavioral/Observer | Decouples publisher from subscriber set | Ordering, lifetime, and error handling become indirect | There is one required caller that should invoke directly |
| Encapsulate a request for queuing, undo, or dispatch | Software Architecture/Patterns/Design Patterns/Behavioral/Command | Turns an operation into data with explicit execution | Boilerplate around simple method calls | No delayed, logged, retried, or reversible execution exists |
Similar structure does not imply the same pattern. Proxy and Decorator both wrap an interface, but Proxy controls access while Decorator adds responsibility. State and Strategy both delegate behavior. They differ by intent rather than by who selects the delegate: State transitions may be defined by the context or by the concrete states, while a client usually supplies a Strategy as policy. When the variation disappears, the abstraction no longer earns its cost and can be collapsed.
Questions
What is a design pattern?
A design pattern is a named, reusable solution to a recurring design problem. It describes the problem, how a set of objects collaborates to address it, and the consequences of using it. It is not ready-made code or a fixed class diagram.
- Name: a shared word for the design. Saying Strategy communicates that an algorithm varies behind a stable contract.
- Problem: the pressure the pattern responds to, such as an unknown set of dependents that must be notified of state changes (Observer).
- Solution: the roles and their collaboration, adapted to each codebase rather than copied literally.
- Consequences: what the pattern buys, such as replaceable behavior, and what it costs, such as extra types and indirection.
The best-known catalog is the Gang of Four book, which describes 23 object-oriented patterns grouped as creational, structural and behavioral. A pattern is justified only when its problem actually exists in the code; otherwise its indirection is pure cost.
GoF: Design Patterns: Elements of Reusable Object-Oriented Software · Design Patterns overview · Choose a pattern by intent and cost
How do the GoF categories (creational, structural, behavioral) relate to choosing a design pattern?
The three categories group the GoF patterns by the kind of problem they address. They narrow where to look, but the concrete design pressure and each pattern’s intent decide which pattern fits.
Category Problem it addresses Examples Creational Where construction decisions live: which concrete class is created, how a complex object is assembled, or how instances are copied or limited. Factory Method, Abstract Factory, Builder, Prototype, Singleton Structural How objects and types are composed into larger structures, and how interfaces are adapted or wrapped. Adapter, Composite, Decorator, Facade, Proxy Behavioral How responsibilities and communication are distributed among objects. Strategy, Observer, Command, State, Template Method A category alone cannot decide, because patterns with a similar structure serve different intents. State and Strategy both delegate behavior to another object, but they differ by intent rather than by who selects the delegate: State lets behavior follow the context’s current state, with transitions defined by the context or by the state objects, while Strategy makes an interchangeable algorithm a policy that a client usually supplies. The useful starting point is the pressure in the code, such as an algorithm that must vary or an interface that does not match. The pattern whose intent addresses that pressure is the candidate.
GoF: Design Patterns: Elements of Reusable Object-Oriented Software · Creational patterns at a glance · Choose a pattern by intent and cost
When does using a design pattern become an anti-pattern?
A pattern becomes an anti-pattern when the indirection it adds costs more than the variation or responsibility boundary it protects. The pattern name alone never pays for the extra complexity.
Every pattern adds cost:
- more types or delegates to read and maintain
- an extra hop between a caller and the behavior
- execution order, lifetime or error handling that becomes harder to follow
Typical signs that the cost is not repaid:
- No real variation: an Abstract Factory with only one product family, or a Strategy replacing a small conditional that is stable and clearer.
- Trivial construction: a Builder around values that a readable constructor or options record already handles.
- No boundary to protect: an Adapter between two contracts that the same team controls and could simply align.
- Flexibility nobody uses: a Command wrapper where nothing is delayed, logged, retried or undone, or an Observer with one required dependent that could be called directly.
When the variation that justified a pattern disappears, collapsing the abstraction back into direct code removes its cost.
GoF: Design Patterns: Elements of Reusable Object-Oriented Software · Choose a pattern by intent and cost
How do Adapter, Decorator, and Proxy differ despite their similar wrapper shape?
An object Adapter, a Decorator and a Proxy all wrap another object, but for different reasons. An Adapter translates an incompatible contract into the one a client expects. A Decorator keeps the same interface and adds behavior. A Proxy keeps the same interface and controls access to the real object. A class Adapter adapts through inheritance instead of wrapping an object, so the wrapper comparison describes the object form.
Aspect Object Adapter Decorator Proxy Interface toward the client A different interface from the wrapped object’s: the one the client expects. The same interface as the wrapped object. The same interface as the real object. Responsibility Translating calls and data between two incompatible contracts at one boundary. Adding a responsibility around the call. Several decorators can be stacked at runtime, and their order affects behavior. Deciding whether, when or how a call reaches the real object. Effect on a call It is converted into the wrapped object’s operations, and results are converted back. It normally reaches the wrapped object, with extra behavior before or after. It may be forwarded, deferred or refused according to the access rule. Because their class shapes look alike, the wrapper’s responsibility, not its structure, identifies the pattern.
GoF: Design Patterns: Elements of Reusable Object-Oriented Software · GoF: Adapter (InformIT excerpt) · Choose a pattern by intent and cost