Design Patterns · Review
Choose a Pattern
Choose from the pressure in the code. Explain the boundary, the expected change, and the cost before naming a pattern.
This lesson follows Visitor. It brings the book's foundations and 22 patterns into one retrieval exercise.
A pattern is a reusable design decision for a recurring problem. Choosing one means selecting a boundary that makes an expected change cheaper. The pattern also makes another kind of work more expensive. Say both sides.
Start with the change
Work through a design decision in this order:
- name the concrete change or failure
- mark the responsibility that should vary independently
- describe the simplest design that isolates it
- name the pattern if its intent matches
- state the added cost and when the design would stop being useful
Try it
Retrieve the catalog by the problem
Which part changes: concrete product, matching family, construction steps, configured copy, or instance count?
Factory Method: subclass selects one product
Abstract Factory: factory selects a matching family
Builder: assemble in steps
Prototype: copy a configured object
Singleton: enforce one scoped instance
Which boundary is difficult: an interface mismatch, independent dimensions, a tree, optional layers, a subsystem, repeated state, or controlled access?
Adapter: translate a contract
Bridge: separate two dimensions
Composite: uniform tree operations
Decorator: stack responsibilities
Facade: simplify a subsystem
Flyweight: share repeated immutable state
Proxy: mediate access
Which collaboration changes: routing, requests, traversal, coordination, history, subscriptions, lifecycle, algorithms, steps, or operations across types?
Chain: route through handlers
Command: represent a request
Iterator: own traversal progress
Mediator: coordinate components
Memento: save private state
Observer: notify subscribers
State: vary by lifecycle
Strategy: choose an algorithm
Template Method: preserve a skeleton
Visitor: add operations across stable types
Compare similar shapes by intent
| Similar shape | Ask this question | Decision |
|---|---|---|
| Factory Method / Abstract Factory / Builder | Am I selecting one product, a family, or an assembly process? | product selection / family consistency / staged construction |
| Adapter / Decorator / Proxy / Facade | Am I translating, adding behavior, controlling access, or simplifying? | contract translation / responsibilities / access policy / subsystem doorway |
| Strategy / State / Bridge | Am I selecting an algorithm, advancing a lifecycle, or separating two dimensions? | independent algorithms / transitions / independently growing families |
| Observer / Mediator | Am I maintaining subscriptions or coordinating cooperation? | notification links / centralized interaction rules |
| Command / Memento | Am I representing an action or preserving state? | request object / opaque snapshot |
| Composite / Decorator | Am I combining children or adding a layer to one component? | recursive group / responsibility wrapper |
| Template Method / Strategy | Does variation belong in subclass steps or an object collaborator? | inheritance skeleton / composition |
| Visitor / Iterator | Am I defining work across types or moving through a structure? | operation dispatch / traversal progress |
Check yourself
A wrapper implements the same interface as an expensive service and creates that service only on first use. What intent identifies it?
Correct. The shape resembles several wrappers. Its primary job is mediating access to a service whose creation is delayed.
Not quite. The interfaces already match. Translation is not the design pressure.
Not quite. There is no recursive collection of children.
Say the whole decision
For a report exporter: “Formats keep arriving. Put each formatting algorithm behind a shared contract and inject it into the export workflow. That is Strategy. It keeps the workflow stable, but configuration must choose a format and every formatter must honor the same result contract.”
If subclasses of a framework workflow must choose which writer to create, the same feature may use Factory Method. The feature name “export” does not determine the pattern. The required extension boundary does.
Try it
Change the growth direction
Visitor matches this direction of growth. The initial accept methods create the extension point.
Visitor makes this direction expensive. Ordinary element methods or a simpler type-based operation may fit better.
A pattern cannot supply guarantees its mechanism does not provide
Singleton does not coordinate servers. Observer does not persist events. Command does not make effects reversible. Facade does not make a sequence atomic. State does not serialize concurrent transitions. Name the mechanism for each guarantee the product actually needs.
Retrieve and apply
Check yourself
A report has one stable CSV output and three straightforward options. What is a strong first decision?
Correct. The book's principles help control change. They do not require adding a hierarchy to every feature.
Not quite. Those abstractions each need their own pressure. One stable format does not establish three separate extension problems.
Check yourself
A document has Draft, Review, and Published behavior. Optional logging layers must also be selectable. Must one pattern solve both?
Correct. Separate pressures can justify separate boundaries. Keep the composition understandable and avoid layering patterns without a reason.
Not quite. Patterns can cooperate. The criterion is whether each one earns its cost.
Choose one feature in a small application. Write five lines: pressure, boundary, expected change, cost, and a reason to keep a simpler design. Revisit Design Principles when the pattern name is clear but the responsibility is still vague.
Source: Alexander Shvets, Dive Into Design Patterns (深入设计模式), Chinese edition v2021-1.25. Course synthesis of the foundations and pattern catalog, printed pages 7–383. Explanations, examples, and exercises are adapted for this course.