# Design Patterns

> Design Patterns Advisor

- Skill: `volodymyrkoval/design-patterns` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add volodymyrkoval/design-patterns`
- Raw SKILL.md: https://api.skillmd.com/api/skills/volodymyrkoval/design-patterns/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: volodymyrkoval (https://skillmd.com/u/volodymyrkoval)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/volodymyrkoval/design-patterns

---


# Design Patterns Advisor

A forcing function for pattern thinking. The goal is not to apply patterns — it's to consciously decide whether one fits. Answer the checklist and self-critique questions before committing to a design.

## Step 1 — "Did you consider?" checklist

Work through the relevant groups for the problem at hand. You don't need all groups — skip what clearly doesn't apply. But for every group that *might* apply, consciously decide, don't silently skip.

### Creational
- [ ] Are there complex construction sequences, optional parameters, or multi-step object assembly? → **Builder**
- [ ] Does the caller need to create objects without knowing the concrete type? → **Factory Method / Abstract Factory**
- [ ] Are objects expensive to create and mostly identical? → **Prototype**
- [ ] Should exactly one instance coordinate shared state? → **Singleton** *(see self-critique — often wrong)*
- [ ] Are multiple related families of objects created together? → **Abstract Factory**

### Structural
- [ ] Are there cross-cutting concerns (logging, caching, auth, retry) layered onto an existing interface? → **Decorator** or **Proxy**
- [ ] Do two incompatible interfaces need to work together? → **Adapter**
- [ ] Is there a complex subsystem that callers shouldn't need to understand? → **Facade**
- [ ] Do you have a tree of objects treated uniformly as a whole? → **Composite**
- [ ] Is there a large number of fine-grained objects with shared intrinsic state? → **Flyweight**
- [ ] Do you need to decouple an abstraction from its implementation so both can vary independently? → **Bridge**

### Behavioral
- [ ] Does an algorithm or behavior vary by context and might add variants later? → **Strategy**
- [ ] Does an object's behavior depend on its current state and transitions between states? → **State**
- [ ] Do you need to encapsulate a request as an object (undo, queuing, logging operations)? → **Command**
- [ ] Do multiple objects need to react to events from one source, without tight coupling? → **Observer / Event Bus**
- [ ] Is there a fixed algorithm skeleton with steps that vary? → **Template Method**
- [ ] Do you need to traverse a structure without exposing it? → **Iterator**
- [ ] Do you need to add operations to objects without changing their classes? → **Visitor**
- [ ] Do objects need to communicate without knowing about each other? → **Mediator**
- [ ] Do you need to restore an object to a previous state? → **Memento**
- [ ] Do you need lazy evaluation of an expensive computation? → **Chain of Responsibility** or **Lazy Proxy**

### Data & Persistence
- [ ] Do you need to decouple domain logic from data access details? → **Repository**
- [ ] Do multiple repositories need to share a transaction boundary? → **Unit of Work**
- [ ] Do you need expressive, composable query conditions as objects? → **Specification**
- [ ] Is domain data mapping complex and varied? → **Data Mapper**

### Architectural
- [ ] Do read and write workloads have different scaling, model, or complexity needs? → **CQRS** *(read references/architectural.md)*
- [ ] Does a multi-step workflow span services and need rollback / compensation on failure? → **Saga** *(read references/architectural.md)*
- [ ] Should domain events drive side effects instead of direct calls? → **Domain Events / Event-Driven** *(read references/architectural.md)*
- [ ] Do you need a full audit trail of state changes? → **Event Sourcing** *(read references/architectural.md)*
- [ ] Is there a reusable selection / filtering rule that needs to be combined and tested independently? → **Specification** *(read references/architectural.md)*

---

## Step 2 — Quick reference table

| Pattern | Use when | Skip when |
|---------|----------|-----------|
| **Builder** | Construction has ≥3 optional parts or a required sequence | A plain constructor or named parameters do the job |
| **Factory Method** | Caller shouldn't own the concrete type; type may vary by subclass | Type is fixed and caller can just `new` it |
| **Abstract Factory** | Multiple related objects must be created as a consistent family | Only one object type is being created |
| **Prototype** | Cloning is cheaper than fresh construction; templates exist | Objects are cheap or vary little |
| **Singleton** | Truly one instance coordinates shared, mutable, process-wide state | Two instances would work fine; use DI instead |
| **Adapter** | Two incompatible interfaces must collaborate | You control both sides — change one instead |
| **Decorator** | Stack cross-cutting concerns without subclassing | There's only one concern; a subclass or wrapper is clearer |
| **Proxy** | Control access, add lazy loading, or log before delegation | Direct access works; a function wrapper suffices |
| **Facade** | Simplify a complex subsystem behind a single entry point | The subsystem is already simple |
| **Composite** | Trees of objects treated uniformly (files/folders, UI trees) | There's no recursive structure |
| **Bridge** | Abstraction and implementation must vary independently | Only one dimension varies |
| **Flyweight** | Thousands of near-identical objects; intrinsic state dominates | Object count is small |
| **Strategy** | An algorithm varies by context and callers swap it | Only one algorithm exists now and none are planned |
| **State** | Behavior changes significantly based on discrete state transitions | Logic is simpler as a flag or enum check |
| **Command** | Encapsulate requests for undo, queuing, or logging | Fire-and-forget calls; no replay/undo needed |
| **Observer** | Multiple consumers react to events from one producer | One consumer; a direct call is clearer |
| **Template Method** | A fixed algorithm skeleton has variable steps | Steps vary so much they share no skeleton |
| **Iterator** | Traverse a collection without exposing its internals | Language provides built-in iteration |
| **Visitor** | Add operations to a stable object hierarchy without modifying it | The hierarchy changes often (prefer polymorphism) |
| **Mediator** | Many objects communicate in complex ways; reduce coupling | Two or three objects; direct references are fine |
| **Memento** | Snapshot and restore state (undo stacks, game saves) | State is cheap to recompute |
| **Chain of Responsibility** | A request passes through a pipeline of handlers, any of which may handle it | Exactly one handler; routing is fixed |
| **Repository** | Domain logic must be isolated from persistence mechanics | You're in a CRUD app; Active Record is fine |
| **Unit of Work** | Multiple repositories share a transaction that must succeed or fail together | Single repository; the ORM handles transactions |
| **Specification** | Business rules are reusable, combinable, and independently testable | Rules are simple one-off predicates |
| **CQRS** | Reads and writes diverge in model, scaling, or team ownership | Simple CRUD where one model serves both |
| **Saga** | Multi-step workflows span services; partial failure needs compensation | The workflow is in one service/transaction |
| **Domain Events** | Side effects should be decoupled from the action that caused them | Direct method calls communicate intent clearly |
| **Event Sourcing** | Full audit trail required; temporal queries on state history needed | Current state is all you need |

---

## Step 3 — Self-critique (answer before finalizing)

These questions exist because pattern application is a common source of premature abstraction. A pattern that can't pass this checklist shouldn't be in the plan.

- [ ] **YAGNI test**: Is there actual evidence of the variation or growth that justifies this pattern, or is it a guess? One concrete case does not make a pattern.
- [ ] **Simpler alternative**: Could a well-named function, a plain class, or a direct dependency injection solve this without the pattern's indirection?
- [ ] **Indirection payoff**: What specific, concrete benefit does this pattern's extra layer buy? Name it — "flexibility" alone doesn't count.
- [ ] **Team legibility**: Will the next developer recognize this pattern immediately, or will it read as unnecessary machinery?
- [ ] **Testability**: Does this pattern make the code easier to test, or does it add seams that require more mocking?
- [ ] **Singleton check**: If you're considering Singleton — can a dependency injected instance serve the same purpose? (Almost always yes.)
- [ ] **Architectural pattern check**: If considering CQRS, Saga, or Event Sourcing — is the problem genuinely distributed/multi-service, or would a simpler in-process solution work? These patterns carry significant operational cost.

---

## How planner and lead-dev use this skill

**Planner:** After drafting component responsibilities, invoke this skill. Run Step 1 for each component. Patterns that pass self-critique become explicit todos. Patterns that fail self-critique get noted as "considered and rejected — reason: X" in Technical Notes.

**Lead-dev:** Before the first Red phase on a design-heavy todo, invoke this skill to validate the chosen approach. If a better pattern emerges, raise it before writing tests — changing the structural decision mid-cycle is expensive.

**Output format:** State the pattern, the concrete signal that justified it, and the self-critique answer that cleared it. Example:
> Strategy — PaymentProcessor behavior varies by provider (Stripe, PayPal, bank transfer) and new providers are a confirmed roadmap item (Q3). Simpler alternative: a switch statement would work now but breaks OCP on every new provider. Indirection payoff: each provider isolated and independently testable.

For architectural patterns (CQRS, Saga, Event Sourcing, Domain Events, Specification), read `references/architectural.md` before recommending.

