Design Patterns
When to use a pattern
The interviewer asks for a parking lot. You start listing names: Strategy, Factory, Singleton, Observer, Decorator. Ten minutes later you still have no Ticket class. Patterns are names for recurring fixes. They are not a checklist to tick off.
The book named 23 patterns in three families. Five hide how objects are created. Seven hide how objects are wired together. Eleven hide how objects divide a job. Pick the family first; the pattern name comes after.
The four moves
Name the smell
What keeps changing, and who knows too much?
Name the family
Create, structure, or behavior — pick one first.
Name the pattern
Only if a simpler class or map will not do.
Show the extension point
A new type becomes a class, not a new if.
Family compass
What is actually varying?
comes first. Find the unstable part. Hide it behind a stable interface. Then pick the family. A is the proof: a new requirement becomes a new class, not a new if in the old one.
The smell is a switch. The pattern is a seam.
Use a pattern when you can name the in plain language. “Every new vehicle type edits three switches” is Factory Method. “Hourly, airport, and event fees keep landing in ParkingLot” is Strategy. “A payment SDK does not look like Payable” is Adapter. If you cannot name the pain in plain language, you do not need the pattern yet.
// Smell: every new fee rule edits ParkingLot.
class ParkingLot {
Money fee(Ticket t, Instant exit) {
if (t.kind() == Kind.HOURLY) return hourly(t, exit);
if (t.kind() == Kind.AIRPORT) return airport(t, exit);
throw new IllegalArgumentException();
}
}
// Seam: PricingStrategy is the named variation.
// That is Strategy — a behavioral pattern — not a creational one.
class ParkingLot {
private final PricingStrategy pricing;
ParkingLot(PricingStrategy pricing) { this.pricing = pricing; }
Money fee(Ticket t, Instant exit) { return pricing.fee(t, exit); }
}Notice the family. The switch was about how to compute a fee, not about which class to construct. That is behavioral. A factory would be the wrong first name even though both hide a switch.
All 23 Gang of Four patterns
Five creational, seven structural, eleven behavioral. Each card is a full page. Open the one that matches the smell — do not memorize the list as a checklist.
Creational — 5
Factory Method picks one product. Abstract Factory picks a matching family. Builder assembles a complex object step by step. Prototype clones a ready object. Singleton is “one instance in the process” — and in interviews you usually do not want it.
Factory Method
Which class to new keeps spreading.
Open the pageAbstract Factory
A matching family of products must stay consistent.
Open the pageBuilder
Too many constructor args and optional parts.
Open the pagePrototype
A ready object already exists; reconstruct is messy.
Open the pageSingleton
Truly one process resource — and usually you do not want this.
Open the pageStructural — 7
Adapter makes a foreign type look like yours. Bridge splits an abstraction from its implementations. Composite treats a leaf and a tree the same. Decorator wraps to add behavior. Facade hides a noisy subsystem behind one entry point. Flyweight shares heavy unchanged state. Proxy stands in for access, laziness, or a remote stub. See also Adapter vs Facade.
Adapter
Foreign type, wrong interface.
Open the pageBridge
Two axes of change multiply into a class explosion.
Open the pageComposite
Leaf and tree must share one contract.
Open the pageDecorator
Add behavior, keep the same interface.
Open the pageFacade
Hide a noisy subsystem behind one entry point.
Open the pageFlyweight
Share the heavy, unchanged part of many objects.
Open the pageProxy
Stand-in for access, laziness, or a remote stub.
Open the pageBehavioral — 11
Chain of Responsibility passes a request along handlers. Command turns “do this” into an object. Interpreter models a tiny language. Iterator walks a collection without exposing it. Mediator replaces a web of pairwise calls. Memento saves a snapshot. Observer notifies listeners. State lets the current state decide behavior. Strategy swaps an algorithm. Template Method fixes the skeleton and varies the steps. Visitor adds an operation across a stable tree of types.
Chain of Responsibility
A pipeline of handlers that may stop the walk.
Open the pageCommand
Queue, undo, or replay a request as an object.
Open the pageInterpreter
A tiny language modeled as objects.
Open the pageIterator
Walk a collection without leaking its structure.
Open the pageMediator
Many-to-many chatter that needs one hub.
Open the pageMemento
Undo without exposing private fields.
Open the pageObserver
Notify listeners without naming them all.
Open the pageState
Behavior changes with the current state.
Open the pageStrategy
Swap an algorithm without editing the context.
Open the pageTemplate Method
Share a skeleton, vary the steps.
Open the pageVisitor
Add an operation across a stable type tree.
Open the pageSmell to family to pattern
| Smell | Family | Pattern |
|---|---|---|
| Which class to new keeps spreading. | Creational | Factory Method |
| A matching family of products must stay consistent. | Creational | Abstract Factory |
| Too many constructor args and optional parts. | Creational | Builder |
| A ready object already exists; reconstruct is messy. | Creational | Prototype |
| Truly one process resource — and usually you do not want this. | Creational | Singleton |
| Foreign type, wrong interface. | Structural | Adapter |
| Two axes of change multiply into a class explosion. | Structural | Bridge |
| Leaf and tree must share one contract. | Structural | Composite |
| Add behavior, keep the same interface. | Structural | Decorator |
| Hide a noisy subsystem behind one entry point. | Structural | Facade |
| Share the heavy, unchanged part of many objects. | Structural | Flyweight |
| Stand-in for access, laziness, or a remote stub. | Structural | Proxy |
| A pipeline of handlers that may stop the walk. | Behavioral | Chain of Responsibility |
| Queue, undo, or replay a request as an object. | Behavioral | Command |
| A tiny language modeled as objects. | Behavioral | Interpreter |
| Walk a collection without leaking its structure. | Behavioral | Iterator |
| Many-to-many chatter that needs one hub. | Behavioral | Mediator |
| Undo without exposing private fields. | Behavioral | Memento |
| Notify listeners without naming them all. | Behavioral | Observer |
| Behavior changes with the current state. | Behavioral | State |
| Swap an algorithm without editing the context. | Behavioral | Strategy |
| Share a skeleton, vary the steps. | Behavioral | Template Method |
| Add an operation across a stable type tree. | Behavioral | Visitor |
Cousins that get mixed up
Factory Method vs Abstract Factory vs Builder
Adapter vs Decorator vs Proxy vs Facade
Strategy vs State vs Template Method vs Command
Command vs Memento
Common mistake
Treating 23 names as a checklist
A design that “uses” Singleton, Factory, Observer, and Decorator in forty-five minutes is usually a God object with extra types. Name the variation. Use one or two patterns. Leave the rest unnamed.
Common mistake
Starting with the pattern instead of the smell
“I will use Abstract Factory” is not an answer. “Vehicle types keep multiplying and three controllers each have a switch” is. Then Factory Method — or a registry — is the fix.
Useful extras that are not GoF
Machine-coding rounds also reward a few names that are not in the 23. Null Object is a do-nothing implementation. Specification composes rules. Registry looks up a handler by name. Policy names a business rule. Dependency injection is how tests replace clocks and stores.
Start from Protected Variations and SOLID. Patterns are how those ideas show up as types.
What interviews reward
Name one or two extension points, then write Java
State the pain in plain language. Name the family. Name at most two patterns. Show where a new type plugs in. Then write the interface and one implementation. That is stronger than reciting all 23 names.