About gof-strategy
A skill explaining the Strategy design pattern for developers choosing among alternative algorithms. It covers when to encapsulate behavior behind a shared interface and when that indirection is unnecessary.
Key features
- 01Encapsulate alternative algorithms
- 02Delegate behavior through an interface
- 03Swap strategies at runtime
- 04Compare Strategy with related patterns
Use cases
- 01Replacing type-based algorithm branches
- 02Varying behavior without subclass proliferation
- 03Adding a second algorithm with a clear need
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill gof-strategyAfter installing, type/gof-strategyin Claude Code to confirm it loaded.
Details
From the project READMEOne-line summary
Encapsulate each member of a family of algorithms behind a common interface and let the client compose the one it needs at runtime — instead of hardcoding the algorithm or branching on a type flag.
When to use this skill
- A class has a branching
switch/ifon a "type" field that selects between alternate algorithms (sort orders, pricing rules, validation strategies). - Subclassing has been used to vary one piece of behavior, leading to a combinatorial explosion of classes.
- The set of algorithms is expected to grow.
- Two classes share most behavior but differ in a single dimension (e.g.,
MallardDuckandRubberDuckdiffer only in how they quack and fly).
When NOT to use this skill
- Only one algorithm exists and no second one is in sight — adding the indirection is YAGNI.
- The varying behavior involves a sequence of steps with mostly identical structure — that's
gof-template-method. - The variation is what gets composed not how it computes — that's often
gof-decorator.
Core content
Strategy decouples what the client does from how it does it. The client holds a reference to a strategy object via a small interface; the concrete strategy plugs in at construction (or via a setter to change at runtime).
Composition over inheritance: instead of subclassing to vary one method, inject a small object that owns that method. Each strategy is independently testable and can be swapped without touching its host.
Pseudo-shape:
- Define an interface
Strategy { operate(input) }. - Concrete strategies implement it:
StrategyA,StrategyB, … - The context class holds a
Strategyand delegates:context.do(input) { strategy.operate(input) }.
Decision heuristics
- Apply when you genuinely have ≥2 algorithms today, or one today and a strong, near-term reason for a second.
- Prefer Strategy to subclass-per-algorithm explosion.
- If the strategies are stateless, they can be
objectinstances (singletons) rather than allocated per-context.
Anti-patterns
- Introducing Strategy for a single algorithm "in case we need more later" — the indirection cost shows up immediately, the benefit may never arrive.
- Strategy objects that carry too much state — Strategy is meant for behavior; if the strategy carries large per-call state, reconsider the boundary.
- Naming strategies for how they implement (
FastSortStrategy,SlowSortStrategy) rather than what they mean in the domain (PriorityFirstSort,ChronologicalSort).
See also
gof-state— same structure, different intent (Strategy varies what's computed; State varies behavior across object lifecycle).gof-template-method— when the variation is the steps within an algorithm, not the whole algorithm.gof-command— for parameterizing operations rather than algorithms.gof-kotlin-idioms— in Kotlin, a strategy is often just a function-typed parameter(T) -> R; no interface needed.
References
- Head First Design Patterns (2nd ed), Ch. 1 ("Welcome to Design Patterns") — the canonical Strategy chapter, framed around the Duck simulator example.