Last quarter the discount rule was one if. This quarter it is a forty-line type-code forest: percent off, flat off, buy-one-get-one, a loyalty multiplier, and a branch that only exists for Black Friday. The next promotion will edit the same method again. The tests for the old promotions will run for a change that has nothing to do with them.

That is the kind of pain a design pattern is for. Not “the book listed twenty-three names,” and not a code-review checklist.

A design pattern is a named way to arrange types so a specific change stays local. Principles such as SOLID say why a seam should exist. Patterns say how this one usually looks once you have already felt the pain.

This post is the series glossary and index: the three families, the shared lab the later posts reuse, when a pattern is ceremony, and a living catalog of every post in this section. Later posts link back here instead of re-lecturing Gang of Four.

How to use this page

You do not need to read twenty-three posts in book order.

  • Jump by family — creational, structural, or behavioral — if you already know the name and want the pain it targets.
  • Follow Start here if you want the patterns that show up in real code (and interviews) first.
  • Treat (upcoming) titles as the map, not a 404. Published titles are links. Titles marked (upcoming) are not live yet — do not invent a URL. This page is updated when one ships.

Each pattern post stands alone for its own title. Definitions of the families, the lab domain, and the cargo-cult failure modes live here.

Principles first, then a named shape

If you have just finished the SOLID series, the relationship is:

SOLID asksA pattern answers
Can I add behavior without editing the core?Strategy, Decorator, Factory Method
Can a subtype keep the caller’s contract?Adapter (honest wrap) vs a lying subclass
Can I test policy without I/O?Strategy, Proxy, Command as seams you can fake
Who owns new?Factory Method, Abstract Factory, Builder — at the edge

Do not reach for a pattern to “do SOLID.” Reach for one when a change you can name is expensive, and the named arrangement matches that change. The SOLID hub stays the glossary for the five letters; this page stays the map for the named solutions.

Note: MVC, Repository, DAO, and “dependency injection as a pattern” are not in this catalog. They are architectural or framework conventions. Dependency Inversion already has a post in the SOLID series: Depend on Abstractions, Not on new.

The three families, one sentence each

The Gang of Four grouped twenty-three patterns by what they vary. That grouping is still the cheapest way to navigate.

Creational — who is allowed to say new

Creational patterns move object construction out of the code that uses the object, so the user is not welded to a concrete type.

The smell is a policy class that names Stripe, Razorpay, and a test double in the same method, or a constructor with twelve parameters that nobody can call correctly twice.

Structural — how types sit next to each other

Structural patterns compose or wrap types so you can add, hide, or translate a surface without rewriting the thing being wrapped.

The smell is a subclass explosion (“AuditedRetryingCachedGateway”), a vendor SDK leaking into every caller, or a facade that is really just a bag of unrelated methods.

Behavioral — who does the work, and when

Behavioral patterns assign responsibility for an algorithm, a reaction, or a conversation so the participants can change independently.

The smell is a growing switch on a type code, a publisher that knows every listener by name, or an undo feature implemented as a pile of boolean flags.

The lab domain: order, payment, discount

Most posts in this series reuse the same tiny checkout domain as the SOLID series, so you are not re-learning a scenario. Four names, used consistently:

TypeRole
OrderThe data: id, customer email, line items, total
PaymentGatewayCharges an order through some provider
DiscountPolicyTurns an order total into the amount payable
OrderProcessorThe policy that coordinates the above

Order stays a plain data carrier:

public record Order(String id, String customerEmail, List<LineItem> items, BigDecimal total) {}

public record LineItem(String sku, int quantity, BigDecimal unitPrice) {}

If records are new to you, Java Records: Immutable Data Without the Boilerplate covers the shape. The SOLID god-service starting point is in SOLID Roadmap — this series assumes that method has already been split, and asks a different question: once the seams exist, which named arrangement fits the next variant?

A few patterns need a second tiny example because checkout does not naturally grow a tree, a million identical objects, or a grammar. Those are called out in the catalog: Composite, Flyweight, and Interpreter. Everything else should be readable against Order / PaymentGateway / DiscountPolicy.

When patterns are cargo-cult

Patterns go wrong more often from premature naming than from ignorance. The tell is the same one as SOLID: indirection with no second implementation and no second reason to change.

Concrete anti-patterns to refuse:

  • A Strategy with one implementer. PercentDiscount behind DiscountPolicy, forever alone, plus a config key to select the only option. That is two files to open instead of one.
  • Singleton as a global bag. A AppContext.getInstance() that holds the database, the clock, and the current user. You have not limited instances; you have hidden every dependency.
  • Visitor on a closed set you own. If the types are a sealed hierarchy and the operations are few, an exhaustive switch is honest. Visitor pays off when operations keep arriving and the element set does not.
  • Abstract Factory for one family. Three factory classes to produce one gateway, one notifier, and one repository that never vary together.
  • Decorator wrapping nothing extra. LoggingGateway that logs a line and forwards, with no second wrapper and no plan for a third. A method call at the call site was enough.
  • Command objects for a method you run once. ProcessOrderCommand that is constructed and execute()d in the same line as the old processor.process(order) call.

The healthy trigger is a variant you can point at in the git log. Two discount rules, a second payment SDK, a queue that needs undo, a third notification channel. Name the change. If you cannot, do not name a pattern either.

Note: Library and framework code plays by different rules. A published API often needs a stable seam before the second caller exists, because the callers are outside your repository. Application code can wait for evidence.

The catalog

Published titles are links. Titles marked (upcoming) are not live yet — they will become links as those articles ship. Jump to the family that matches the pain; do not treat the book order as a reading order.

Creational

PatternPain it targetsPost
Factory MethodCallers should not name the concrete type they receiveFactory Method: Let Subclasses Decide Which Object to Build
Abstract FactoryA family of related objects must vary togetherAbstract Factory: Families of Objects Without Naming the Concrete Types
BuilderConstruction has many optional steps and a telescoping constructorBuilder: Assemble Complex Objects Step by Step
PrototypeCopying a configured object is cheaper than rebuilding itPrototype: Copy an Object Instead of Reconstructing It
SingletonExactly one instance must exist — and you can name whySingleton: One Instance, Used Carefully

Structural

PatternPain it targetsPost
AdapterAn existing client cannot speak a vendor’s typesAdapter: Make Incompatible Types Talk
BridgeAn abstraction and its implementations need to vary independentlyBridge: Split Abstraction from Implementation
CompositeA tree of parts should be usable as one partComposite: Treat Trees of Objects as One
DecoratorBehavior should wrap an object without a subclass per combinationDecorator: Add Behavior Without Subclassing the Core
FacadeCallers are drowning in a subsystem’s typesFacade: One Simple Front for a Messy Subsystem
FlyweightMany similar objects share a large immutable payloadFlyweight: Share What Does Not Change
ProxyYou need a stand-in (lazy, remote, access control) for a real objectProxy: Stand In for an Object You Cannot Touch Directly

Composite, Flyweight, and Interpreter use a second tiny example on their own posts; the pain column still tells you when to open them.

Behavioral

PatternPain it targetsPost
Chain of ResponsibilitySeveral handlers might own a request; none should hard-code the nextChain of Responsibility: Pass a Request Until Someone Handles It
CommandA request must be queued, logged, or undone as an objectCommand: Turn a Request into an Object
InterpreterA small language needs evaluatingInterpreter: Represent a Grammar and Evaluate It
IteratorCallers must walk a collection without seeing its structureIterator: Walk a Collection Without Exposing Its Guts
MediatorColleagues know too many of each other’s namesMediator: Keep Colleagues from Talking to Each Other
MementoYou need a snapshot without exposing private fieldsMemento: Snapshot State Without Breaking Encapsulation
ObserverMany dependents must react when one object changesObserver: Notify Dependents When Something Changes
StateBehavior should change when internal state changesState: Change Behavior When Internal State Changes
StrategyAn algorithm should be swappable without editing callersStrategy Pattern: Swap Algorithms Without Editing Callers
Template MethodThe skeleton of an algorithm is stable; a few steps varyTemplate Method: Freeze the Skeleton, Vary the Steps
VisitorNew operations keep arriving; the element types do notVisitor: Add Operations Without Changing the Elements

Start here

Book order is a catalog, not a curriculum. If you are picking a first path through this section, use interview-and-production frequency, not chapter numbers. Linked titles are live; (upcoming) titles are not.

  1. Strategy — swap an algorithm
  2. Factory Method: Let Subclasses Decide Which Object to Build
  3. Observer: Notify Dependents When Something Changes
  4. Decorator: Add Behavior Without Subclassing the Core
  5. Adapter: Make Incompatible Types Talk
  6. Builder: Assemble Complex Objects Step by Step
  7. Singleton: One Instance, Used Carefully
  8. Template Method: Freeze the Skeleton, Vary the Steps
  9. Facade: One Simple Front for a Messy Subsystem
  10. Command: Turn a Request into an Object

Wave 2:

  1. Proxy: Stand In for an Object You Cannot Touch Directly
  2. Composite: Treat Trees of Objects as One
  3. State: Change Behavior When Internal State Changes
  4. Chain of Responsibility: Pass a Request Until Someone Handles It
  5. Abstract Factory: Families of Objects Without Naming the Concrete Types
  6. Iterator: Walk a Collection Without Exposing Its Guts

Wave 3 (easy to over-apply):

  1. Bridge: Split Abstraction from Implementation
  2. Flyweight: Share What Does Not Change
  3. Mediator: Keep Colleagues from Talking to Each Other
  4. Memento: Snapshot State Without Breaking Encapsulation
  5. Prototype: Copy an Object Instead of Reconstructing It
  6. Visitor: Add Operations Without Changing the Elements
  7. Interpreter: Represent a Grammar and Evaluate It

Read the post that matches the pain you have today. Come back here for the family and the “when to skip it” test.

Cheat sheet

Creational   who says `new`              -> Factory Method, Abstract Factory, Builder, Prototype, Singleton
Structural   how types sit together      -> Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy
Behavioral   who does the work, and when -> Strategy, Observer, Command, Template Method, State, ...

Trigger to apply: a named variant already exists (or is on the ticket)
Trigger to stop:  one implementation, no pending second
Not in this map:  MVC, Repository, DAO, DI-the-framework
Scoreboard:       files touched per new variant, tests that should not have broken

Do:

  • Start from the change request, then name the pattern that makes that change an addition.
  • Keep data types dumb (records) and put the varying algorithm behind one small interface.
  • Let construction live at the edge — main, a config class, or your DI container.
  • Link back here from later posts rather than re-defining the three families.

Don’t:

  • Introduce a pattern for a variation your product does not have.
  • Treat the twenty-three names as a code-review rubric.
  • Confuse a pattern with a principle: Strategy is one shape that serves Open-Closed; it is not a requirement of Open-Closed.
  • Add MVC, Repository, or a DI framework to this list and call it Gang of Four.

Wrap-up

Design patterns are a vocabulary for arrangements you have already earned. Creational patterns keep new out of policy. Structural patterns wrap, hide, or compose types. Behavioral patterns move an algorithm, a reaction, or a conversation so the next variant does not edit every participant.

The catalog on this page is the map of the section. Every Gang of Four name has a post; start with the algorithm that is already growing an if forest — that is Strategy, and it is the cheapest first step in this series.

Continue with Strategy Pattern: Swap Algorithms Without Editing Callers