You've encountered a concrete object-oriented design problem and need a proven structural solution. This skill is appropriate when:
Before starting, verify:
new ConcreteClass() proliferation (Cause 1), deep inheritance hierarchies (Cause 7), classes doing too many unrelated things (Cause 6)Grep for new , extends, implements patterns to map existing structureIterator, Python's context managers as a form of Template Method); note where native constructs already cover the needYou have enough to proceed if you can articulate: (a) what problem exists, and (b) what the solution should enable. If only (a) is known, the redesign-cause diagnosis (Step 3) will derive (b).
ACTION: Use TodoWrite to track the steps, then articulate the design problem in structured form.
WHY: Vague problems produce vague pattern matches. Forcing a structured framing surfaces the real constraints and eliminates patterns that technically apply but don't fit the actual need.
TodoWrite:
- [ ] Step 1: Frame the problem
- [ ] Step 2: Classify by purpose and scope
- [ ] Step 3: Diagnose redesign causes
- [ ] Step 4: Check variability requirements
- [ ] Step 5: Compare candidate patterns
- [ ] Step 6: Produce recommendation with trade-offs
Capture these four elements from the user's description:
| Element | Question to answer |
|---|---|
| --------- | ------------------- |
| Context | What type of system/component is this? |
| Problem | What is currently wrong or inflexible? |
| Forces | What constraints must the solution respect? (performance, simplicity, existing code) |
| Goal | What must the solution make possible? |
If any element is unclear, ask one targeted question before proceeding.
ACTION: Narrow the candidate set using the purpose × scope classification matrix from references/pattern-catalog.md.
WHY: The 23 GoF patterns split cleanly into three purposes and two scopes. Getting this classification right eliminates 15–20 patterns immediately. It also forces precision about what kind of problem you're solving — a creation problem is fundamentally different from a communication problem.
Decision rules:
Purpose:
Scope (within the chosen purpose):
Output: Identify 1–2 most likely purposes. If the problem spans purposes (e.g., creation inflexibility AND tight coupling), note both — you may need two patterns, or one pattern that addresses both.
ACTION: Match the problem description against the 8 causes of redesign in references/redesign-causes.md.
WHY: The GoF identified that most design problems stem from dependencies that make change expensive. Each cause maps directly to the patterns that eliminate that specific dependency. This is the fastest path from "something is wrong" to "here are the patterns that fix it."
Diagnostic questions to ask:
Output: Identify the 1–3 most relevant causes. Cross-reference with the patterns mapped to each cause — this produces a candidate shortlist.
ACTION: Consult references/variability-table.md to identify which patterns encapsulate the aspects of the design that must remain variable.
WHY: This is the "opposite" approach to cause diagnosis — instead of asking what is breaking, ask what must stay flexible. The variability table maps directly from "aspect I want to vary" to pattern. It catches cases where the user knows what they need to keep variable but cannot articulate the pain yet.
Key question: "What concept in this design must be encapsulated so it can change independently?"
Common variability needs and their patterns:
| I need to vary... | Candidates |
|---|---|
| ------------------- | ------------ |
| Which algorithm runs | Strategy, Template Method |
| Which object handles a request | Chain of Responsibility |
| How objects notify each other | Observer |
| The interface exposed to clients | Adapter, Facade |
| An object's behavior by state | State |
| How and when a request executes | Command |
| The structure of a part-whole hierarchy | Composite |
| Responsibilities without subclassing | Decorator |
| How an object is located/accessed | Proxy |
| Which concrete class gets instantiated | Abstract Factory, Factory Method, Prototype |
Output: Add any new candidates surfaced by variability analysis to the shortlist from Step 3.
ACTION: For each candidate pattern on the shortlist (aim for 2–4), evaluate it against the problem using these lenses:
WHY: Multiple patterns often address the same problem. The right choice depends on trade-offs specific to this context — complexity budget, run-time flexibility needs, relationship to existing code, and what the solution must remain open to in the future.
Evaluation lens for each candidate:
| Lens | Question |
|---|---|
| ------ | ---------- |
| Fit | Does the pattern's intent directly address the core problem? |
| Scope match | Does it operate at class or object scope — which is right here? |
| Complexity cost | How many new classes/interfaces does it introduce? Is that justified? |
| Run-time flexibility | Does it need to vary at run-time or compile-time? |
| Composition | Does it work with patterns already in use, or conflict? |
| Over-engineering risk | Does the flexibility it provides actually apply to this problem's future? |
Pattern relationship check: Consult the "Pattern Relationships" section in references/pattern-catalog.md to identify whether candidates are alternatives (choose one), complements (use both), or sequenced (use first one, then the other as the system evolves).
Output: A ranked shortlist with a 1–2 sentence rationale and a key trade-off noted for each.
ACTION: Deliver a structured recommendation in the following format, then offer to walk through the 7-step application process if the user wants to implement it.
WHY: A recommendation without trade-offs is advice without accountability. The user needs to understand not just what to do but why this pattern beats the alternatives, and what they give up. This enables informed commitment rather than cargo-culting.
Recommendation format:
## Pattern Recommendation: [Pattern Name]
**Category:** [Creational / Structural / Behavioral] — [Class / Object] scope
**Why this pattern:** [1–2 sentences connecting the pattern's intent to the specific problem]
**What it enables:** [What becomes possible that wasn't before]
**Key trade-off:** [What you give up or what additional complexity you accept]
**Alternative considered:** [Runner-up pattern] — [Why it was not chosen]
**Patterns to combine with:** [Any complementary patterns, if applicable]
If the user wants to implement: Walk through the 7-step application process:
LayoutStrategy not just Strategy)Create- prefix for factory methods)Scenario: A UI library has a Button class. Over time, the team added RoundButton, FlatButton, DarkRoundButton, LightFlatButton — 12 subclasses for 3 shapes × 4 themes, and it keeps growing.
Trigger: "Our button hierarchy is exploding. Every new theme or shape doubles the subclass count."
Process:
Output:
## Pattern Recommendation: Bridge
**Category:** Structural — Object scope
**Why this pattern:** Bridge separates the Button abstraction (shape: Round, Flat)
from its implementation (theme: Dark, Light) into two independent hierarchies.
Adding a new theme requires one new class, not N new subclasses.
**What it enables:** Shape and theme can vary independently. 3 shapes × 4 themes = 7 classes total, not 12.
**Key trade-off:** Increases design complexity upfront; adds one level of indirection
(button delegates to its renderer). Justified when both dimensions are genuinely
expected to grow.
**Alternative considered:** Decorator — works well for adding single responsibilities
but doesn't solve two orthogonal variation axes as cleanly as Bridge.
Scenario: An e-commerce checkout class contains a large if/else block selecting between Stripe, PayPal, and bank transfer logic. Adding a new payment method means modifying the checkout class and its tests.
Trigger: "Every new payment provider requires touching the core checkout code."
Process:
if/else dispatch with a family of interchangeable payment-processing objects. Command could encapsulate payment as an undoable request — but undo is not required here and adds unnecessary complexity.Output:
## Pattern Recommendation: Strategy
**Category:** Behavioral — Object scope
**Why this pattern:** Strategy replaces the dispatch block with a PaymentStrategy
interface. Each provider (Stripe, PayPal, bank transfer) is a ConcreteStrategy.
Checkout receives a strategy object at runtime and delegates payment to it.
**What it enables:** New payment providers are new classes, not modifications to Checkout.
Checkout can be tested with a MockPaymentStrategy.
**Key trade-off:** Clients must know which strategy to instantiate. If selection logic
is complex, pair with Abstract Factory to manage strategy creation.
**Alternative considered:** Command — adds request queuing and undo capability not
needed here; over-engineers this use case.
**Patterns to combine with:** Abstract Factory (for strategy instantiation by region/config)
Scenario: A team is integrating a third-party analytics library whose Logger class has an interface incompatible with the IEventTracker interface the rest of the application uses. Source code is unavailable.
Trigger: "We need to use this library's logger but it doesn't match our interface and we can't change it."
Process:
Output:
## Pattern Recommendation: Adapter
**Category:** Structural — Object scope
**Why this pattern:** An Adapter class wraps the third-party Logger and implements
IEventTracker, translating calls between the two interfaces. The rest of the
application only ever sees IEventTracker.
**What it enables:** Library can be swapped for a different provider by swapping the
Adapter, with zero changes to application code.
**Key trade-off:** Each new method in IEventTracker requires a corresponding
translation in the Adapter. If the interfaces diverge significantly, the Adapter
becomes a maintenance burden — consider whether the interfaces can be aligned upstream.
**Alternative considered:** Facade — would simplify the logger API but cannot make it
implement IEventTracker.
| File | Contents |
|---|---|
| ------ | ---------- |
references/pattern-catalog.md | Table 1.1: all 23 patterns by purpose × scope, one-line intents, pattern relationships |
references/variability-table.md | Table 1.2: what each pattern lets you vary independently |
references/redesign-causes.md | 8 causes of redesign with symptoms and mapped patterns |
This skill is licensed under CC-BY-SA-4.0.
Source: BookForge — Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides.
This skill is standalone. Browse more BookForge skills: bookforge-skills
共 1 个版本
暂无安全检测报告