software-design-plugin/skills/design-patterns/SKILL.md
Select a design pattern from a symptom — strategy, observer, factory, adapter, decorator. Use when a structure resists change, or choosing between Gang-of-Four patterns.
npx skillsauth add laurigates/claude-plugins design-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The Gang-of-Four patterns are answers to recurring design problems. Reaching
for a pattern by name invites over-engineering; reaching for one by symptom
keeps the design honest. This skill maps the pressure you're feeling — "this
switch grows every time we add a type", "callers keep re-implementing the same
multi-step setup" — to the pattern that relieves it, and just as importantly
says when no pattern is the right call.
For the per-pattern intent, structure, and a minimal recipe, see REFERENCE.md. This body is the selector.
| Use this skill when... | Use something else instead when... |
|---|---|
| A structure resists a change that should be easy (new type, new behaviour) | Removing duplication with no design pressure → code-quality-plugin:dry-consolidation |
| Choosing between two patterns, or unsure a pattern is warranted | Mechanical refactor toward pure functions → code-quality-plugin:code-refactor |
| Naming the pattern already latent in a pile of conditionals | Complexity metrics on a function → code-quality-plugin:code-complexity |
| Teaching/justifying a pattern choice in review | UI/component composition patterns → component-patterns-plugin |
Match the symptom, not the noun. Confirm the pressure is real before adopting any pattern — each adds an indirection that a one-off conditional does not.
| Symptom you feel | Candidate pattern | Confirm before adopting |
|---|---|---|
| A switch/if on a type code grows with every new variant | Strategy / State | ≥2 variants exist and more are expected |
| Object behaviour changes with an internal mode, transitions are tangled | State | The modes have distinct transitions, not just a flag |
| Many objects must react when one changes | Observer | Reactors are genuinely decoupled from the source |
| Callers hard-code which concrete class to instantiate | Factory Method / Abstract Factory | The choice varies at runtime or by config |
| An interface you need ≠ the interface you have (3rd-party/legacy) | Adapter | You can't change the callee directly |
| Behaviour to add/remove per-instance at runtime, combinatorially | Decorator | Subclass explosion is the alternative |
| Constructing one object needs many ordered steps/options | Builder | The telescoping constructor actually hurts |
| A subsystem is too many moving parts for callers | Facade | Callers only need a common subset |
| An algorithm's skeleton is fixed but steps vary | Template Method / Strategy | The skeleton truly is stable |
| Traversal logic leaks across a collection's clients | Iterator | The collection's shape is non-trivial |
| Operations sprawl across a type hierarchy you can't grow | Visitor | The hierarchy is stable but operations churn |
When two fit: Strategy (composition) over Template Method (inheritance) unless the skeleton must be enforced; State over Strategy when the variants drive transitions between each other.
Parse $ARGUMENTS:
git diff HEAD) and scan it for the symptoms above.Execute this pattern selection:
State, in one line, the change that is currently hard — the new type, the new
reactor, the runtime choice. If the target is code, locate the growing
conditional / hard-coded new / leaking interface that signals it. If nothing
resists change, stop and say so: no pattern is warranted.
Use the selector to pick 1-2 candidates. Read their intent in REFERENCE.md to confirm fit. State explicitly what each pattern costs (an extra interface, an indirection, a new type to maintain).
Apply the "confirm before adopting" gate for the chosen pattern. If the variants don't yet exist (YAGNI) or only one ever will, recommend the simpler conditional and reject the pattern with the reason. Patterns earn their cost only against real, recurring variation.
Emit: the symptom, the chosen pattern (or "no pattern — keep the conditional"), the cost it adds, and the minimal shape from REFERENCE.md mapped onto the target's own types. Keep it a recommendation; don't rewrite the code wholesale.
| Mistake | Correct approach | |---|---| | Picking a pattern by its cool name | Start from the symptom; let it select the pattern | | Adding Strategy for a single, stable behaviour | One implementation = no pattern; YAGNI | | Abstract Factory where a function would do | Use the lightest construct that removes the pressure | | Stacking patterns "to be enterprise-ready" | Each indirection is cost; adopt one only against real variation |
| Pressure | Pattern | Cost |
|---|---|---|
| Type-code switch grows | Strategy / State | One interface + N classes |
| Mode-driven behaviour & transitions | State | State classes + transition wiring |
| Fan-out reactions | Observer | Subscription lifecycle |
| Hard-coded new | Factory | An extra creation seam |
| Wrong interface, can't change callee | Adapter | A thin translation layer |
| Per-instance runtime behaviour | Decorator | Wrapper chain |
code-quality-plugin:dry-consolidation — when the pressure is duplication, not
variation, dedupe instead of patterningcode-quality-plugin:code-refactor — the mechanical moves that introduce the
chosen patternsoftware-design-plugin:design-deep-modules — a pattern should deepen the
interface, not add a shallow indirection layerdevelopment
Debug HTTP APIs: trace requests, inspect headers. Use when a request fails: check status first.
documentation
Render architecture diagrams from text sources. Use when documenting system topology.
tools
Inspect JSON payloads and extract nested fields. Use when parsing API responses.
tools
--- name: no-description allowed-tools: Read --- # No Description This skill has no description and must be dropped with a warning.