Here’s something that tripped me up for years: some patterns have nearly identical class diagrams. Strategy and State. Decorator and Proxy. Draw them on a whiteboard and you can’t tell which is which.
That’s because a pattern isn’t its diagram. A pattern is a diagram plus an intent. Two patterns can share a structure and solve completely different problems. This post puts the eight most commonly confused pairs side by side, using the code we’ve already seen in CornerStore.
Agenda:
- The Cheat Sheet
- Strategy vs State
- Facade vs Mediator
- Decorator vs Proxy
- Command vs Memento for Undo
- Factory Method vs Abstract Factory
- Adapter vs Bridge
- Composite vs Decorator
- Template Method vs Strategy
The Cheat Sheet
If you only remember one line per pair:
| Pair | The difference in one line |
|---|---|
| Strategy vs State | Strategy swaps an algorithm the caller chooses. State changes behaviour as the object’s own lifecycle moves on. |
| Facade vs Mediator | Facade is a front door for outside callers. Mediator coordinates peers that talk through it. |
| Decorator vs Proxy | Decorator adds a responsibility. Proxy controls access. |
| Command vs Memento | Command records the action. Memento records the state. |
| Factory Method vs Abstract Factory | Factory Method creates one product via an overridable method. Abstract Factory creates a matching family. |
| Adapter vs Bridge | Adapter fixes a mismatch after the fact. Bridge separates two dimensions by design. |
| Composite vs Decorator | Composite holds many children. Decorator wraps one component. |
| Template Method vs Strategy | Template Method varies steps through inheritance. Strategy swaps the whole algorithm through composition. |
Strategy vs State
The difference: Strategy swaps an algorithm chosen for an operation. State changes an object’s behaviour as its own lifecycle advances.
| Strategy | State | |
|---|---|---|
| In CornerStore | Shipping cost: standard, express or pickup | The order lifecycle: pending, paid, shipped and so on |
| What varies | The calculation for a shipping method | Which operations an order allows right now |
| Who decides | Pricing picks the strategy from the cart’s shipping method | The current state handles the request and moves the order on |
| Do they know each other? | No. Strategies are independent. | Yes. States create the next state. |
| Smell fixed | S21: a shipping switch | S20: status-string checks |
How to tell which you need:
- Choosing between different ways to do the same job? Strategy.
- Does what’s allowed depend on where the object is in its life? State.
Common mistake: treating every swappable behaviour as Strategy, and missing the transitions that make State useful.
Facade vs Mediator
The difference: Facade gives a caller a simpler way into a subsystem. Mediator coordinates communication between peer objects.
| Facade | Mediator | |
|---|---|---|
| In CornerStore | CheckoutFacade.PlaceOrder |
CartMediator and the four cart widgets |
| What varies | The sequence of services a checkout needs | Who reacts, and in what order, when a widget changes |
| Who decides | The caller chooses to use the facade | Widgets notify the mediator, and the mediator decides what happens next |
| Do the others know it exists? | No. Services behind a facade are unaware of it. | Yes. Every colleague talks to the mediator. |
| Smell fixed | S10: the console ran checkout itself | S17: widgets updated each other directly |
How to tell which you need:
- Does one caller need an easier way to run several services? Facade.
- Do several peers need to react to each other without holding references? Mediator.
Common mistake: both centralise calls, so they get lumped together. A facade simplifies access. A mediator defines interactions.
Decorator vs Proxy
The difference: Decorator adds a responsibility while keeping the interface. Proxy controls access to the object behind that interface.
| Decorator | Proxy | |
|---|---|---|
| In CornerStore | Gift wrap and insurance stacked around a price | Caching and permission checks in front of inventory |
| What varies | Which optional extras are added | Whether, and how, a call reaches the real service |
| Who decides | Pricing stacks the decorators when calculating add-ons | The app wires the proxy in place of the service, and it applies its policy on every call |
| Smell fixed | S09: add-on flags and an if-chain | S12: uncached reads and scattered role checks |
How to tell which you need:
- Adding optional behaviour that stacks up? Decorator.
- Managing access, caching, permissions or lazy creation? Proxy.
Common mistake: “it wraps an object, so it’s a decorator.” Wrapping is the structure. Adding versus controlling is the intent.
Command vs Memento for Undo
The difference: Command records an action that can be run or reversed. Memento records state that can be restored later.
| Command | Memento | |
|---|---|---|
| In CornerStore | Back-office stock adjustments, refunds and cancellations | Cart undo |
| How undo works | Do the opposite: “I subtracted 4, so add 4” | Put the old state back: “here’s what the cart looked like” |
| What else it gives you | An audit log, and the option to queue actions | Encapsulation: the caretaker never sees inside the snapshot |
| Smell fixed | S14: inline actions with no undo or audit | S18: public cart internals copied by hand |
How to tell which you need:
- Need to represent and manage requests, including reversing them? Command.
- Need to restore an object’s earlier values without exposing them? Memento.
Common mistake: assuming any undo feature is one or the other. They solve undo differently, and they can be combined: a command can hold a memento of what it changed.
Factory Method vs Abstract Factory
The difference: Factory Method lets a creator subclass choose one product. Abstract Factory creates a compatible family of products.
| Factory Method | Abstract Factory | |
|---|---|---|
| In CornerStore | Payment creators and processors | Regional pricing and money formatting |
| What varies | Which payment processor gets created | A whole set of regional rules that must match |
| Who decides | A concrete creator overrides CreateProcessor() |
The app picks a regional factory, then asks it for each product |
| Smell fixed | S03: a payment switch building processors | S01: region branches that could mix rules |
How to tell which you need:
- One product varies inside a shared workflow? Factory Method.
- Several products must stay consistent with each other? Abstract Factory.
Common mistake: thinking Factory Method is just a smaller Abstract Factory. Its key idea is the overridable method inside a creator’s workflow, not the creation itself.
Read more: Factory Method · Abstract Factory
Adapter vs Bridge
The difference: Adapter translates an existing interface that doesn’t fit. Bridge separates two dimensions so each can vary independently.
| Adapter | Bridge | |
|---|---|---|
| In CornerStore | ShipFastAdapter around the courier’s XML API |
Order messages on one side, delivery channels on the other |
| When it’s applied | After the fact, to make existing things fit | Up front, to stop a class explosion |
| What varies | The translation to one vendor’s protocol | Message types and channels, independently |
| Smell fixed | S06: checkout calling courier XML directly | S07: one class per message-and-channel combination |
How to tell which you need:
- Using an existing service whose interface doesn’t suit you? Adapter.
- Two things that each need their own variations and combinations? Bridge.
Common mistake: both put an interface between two sides. Adapter is about translation. Bridge is about independent growth.
Composite vs Decorator
The difference: Composite represents a part or a group of parts. Decorator wraps one component to add a responsibility.
| Composite | Decorator | |
|---|---|---|
| In CornerStore | Bundles made of products | Add-ons stacked around a base price |
| Holds | Zero or more children | Exactly one wrapped component |
| Combines results by | Aggregating its children (a bundle sums its parts) | Adding its own bit to the result underneath |
| Smell fixed | S08: a separate bundle path with type checks | S09: add-on flags and an if-chain |
How to tell which you need:
- A tree of parts and groups that callers should treat the same way? Composite.
- Optional behaviour layered around one object? Decorator.
Common mistake: both are recursive, and both hold a component of their own type. Count the children: many means Composite, one means Decorator.
Read more: Composite · Decorator
Template Method vs Strategy
The difference: Template Method fixes an algorithm’s outline in a base class. Strategy hands the whole algorithm to a replaceable object.
| Template Method | Strategy | |
|---|---|---|
| In CornerStore | CSV and JSON report exporters | Shipping cost calculations |
| What varies | A few steps inside a fixed sequence | The entire calculation |
| Mechanism | Inheritance: subclasses override steps | Composition: the caller holds a different object |
| Smell fixed | S22: two exporters duplicating one workflow | S21: a shipping switch |
How to tell which you need:
- The overall sequence is fixed and only some steps differ? Template Method.
- Callers should be able to pick or swap a complete algorithm? Strategy.
Common mistake: they both vary behaviour, so people treat them as interchangeable. The real choice is inheritance or composition, and that choice affects everything else about the design.
Read more: Template Method · Strategy
The Pattern Behind the Patterns
Looking at these eight pairs together, the same lesson keeps coming back: don’t identify a pattern by its shape. Identify it by the question it answers.
- “How do I choose between ways of doing this?” is a different question from “how does this object’s behaviour change over time?”
- “How do I add something?” is different from “how do I control access?”
When you’re reviewing code or designing something new, start with the question. The right pattern usually follows.
For the code side by side, the repository’s comparisons guide has CornerStore excerpts for every pair.
Next up: what happens when all 23 patterns live in the same codebase.
Previous: Visitor · Next: The Capstone