Design Patterns (GoF) — Agent Skill
Actionable rules distilled from Design Patterns: Elements of Reusable Object-Oriented Software (Gamma, Helm, Johnson, Vlissides, 1994). Patterns capture proven designs — not clever tricks. Apply only when the flexibility is actually needed.
Pair with clean-code for implementation quality; domain-driven-design when boundaries and domain models matter.
When to apply
- Choosing how to structure classes/objects for change
- Refactoring toward loose coupling, composability, or pluggable behavior
- Integrating incompatible interfaces, hiding platform details, or extending without subclass explosion
- User says: design pattern, GoF, Strategy, Factory, Observer, Decorator, Adapter
Do not sprinkle patterns for resume-driven design. Read Consequences before applying.
Core laws (non-negotiable)
- Program to an interface, not an implementation — clients depend on abstractions.
- Favor object composition over class inheritance — compose behavior; don't subclass for every variant.
- Encapsulate what varies — each pattern isolates one aspect that changes independently.
- Delegation over inheritance — Strategy, State, Visitor delegate to helper objects.
- Run-time structure ≠ compile-time structure — many patterns build dynamic object graphs (Composite, Decorator, Observer).
- Patterns are not frameworks — you implement them each time; they document intent and trade-offs.
- Only apply when needed — extra indirection has cost (complexity, performance).
Agent workflow
1. PROBLEM — name the design force (what must vary? what causes redesign?)
2. SELECT — match cause of redesign OR aspect to vary (Table below)
3. VALIDATE — check Applicability + Consequences; consider simpler fix first
4. NAME — use domain names + pattern role (e.g. TeXLayoutStrategy)
5. IMPLEMENT — minimal structure; prefer composition
6. VERIFY — clean-code pass; don't over-abstract
Selection order: (1) cause of redesign → (2) intent scan → (3) related patterns graph → (4) compare patterns of same purpose.
Two OOD principles (Ch 1)
| Principle |
Rule |
| Program to interface |
Declare variables, parameters, returns, and attributes as abstract types (interfaces/base classes), not concrete classes. |
| Favor composition |
Reuse by assembling objects; inheritance for true is-a specialization only. Use delegation in Strategy, State, Bridge. |
Causes of redesign → patterns (Ch 1.6)
| Cause |
Patterns |
| Creating objects by explicit class name |
Abstract Factory, Factory Method, Prototype |
| Dependence on specific operations |
Chain of Responsibility, Command |
| Platform (OS/API) dependence |
Abstract Factory, Bridge |
| Dependence on representation/location/implementation |
Abstract Factory, Bridge, Memento, Proxy |
| Algorithmic dependencies |
Builder, Iterator, Strategy, Template Method, Visitor |
| Tight coupling |
Abstract Factory, Bridge, Chain of Responsibility, Command, Facade, Mediator, Observer |
| Extending by subclassing only |
Bridge, Chain of Responsibility, Composite, Decorator, Observer, Strategy |
| Can't modify class conveniently |
Adapter, Decorator, Visitor |
Ask: "What should be variable without redesign?" — pick pattern that encapsulates that aspect.
Pattern catalog — intents (23 patterns)
Creational — object creation
| Pattern |
Intent |
| Abstract Factory |
Interface for creating families of related objects without specifying concrete classes |
| Builder |
Separate construction of complex object from representation; same process → different representations |
| Factory Method |
Interface for creating an object; subclasses decide which class to instantiate |
| Prototype |
Create objects by copying a prototypical instance |
| Singleton |
Ensure one instance + global access (use sparingly — testability cost) |
Choose creational: Factory Method = subclass parameterization. Abstract Factory / Builder / Prototype = object-composition parameterization (factory object). Prototype when classes vary at runtime or cloning is costly to subclass.
Structural — composition & interfaces
| Pattern |
Intent |
| Adapter |
Convert interface so incompatible classes work together (after design — unforeseen coupling) |
| Bridge |
Decouple abstraction from implementation so both vary independently (before — known multiple impls) |
| Composite |
Tree structures; treat individual and composite objects uniformly |
| Decorator |
Attach responsibilities dynamically; alternative to subclassing for extension |
| Facade |
Unified interface to a subsystem — new simplified interface |
| Flyweight |
Share fine-grained objects efficiently via extrinsic state |
| Proxy |
Surrogate controlling access (lazy load, protection, remote, caching) |
Adapter vs Bridge: Adapter fixes two existing interfaces; Bridge plans multiple implementations upfront. Adapter vs Facade: Adapter reuses old interface; Facade defines new higher-level one. Composite vs Decorator vs Proxy: Similar structure; intent differs — part-whole hierarchy vs add behavior vs control access.
Behavioral — algorithms & responsibility
| Pattern |
Intent |
| Chain of Responsibility |
Pass request along chain until something handles it |
| Command |
Encapsulate request as object — parameterize, queue, log, undo |
| Interpreter |
Grammar + interpreter for a small language |
| Iterator |
Sequential access to aggregate without exposing representation |
| Mediator |
Encapsulate how a set of objects interact — reduces explicit references |
| Memento |
Capture/restore internal state without breaking encapsulation |
| Observer |
One-to-many dependency; dependents notified on state change |
| State |
Alter behavior when internal state changes — appears to change class |
| Strategy |
Family of interchangeable algorithms encapsulated |
| Template Method |
Algorithm skeleton in base class; subclasses override steps |
| Visitor |
New operation on elements without changing their classes |
Encapsulating variation: Strategy (algorithm), State (state-dependent behavior), Mediator (interaction protocol), Iterator (traversal). Chain of Responsibility = dynamic open-ended chain.
Aspects you can vary (selection table)
| Pattern |
Vary independently |
| Abstract Factory |
Families of product objects |
| Builder |
How composite object is created |
| Factory Method |
Subclass of object instantiated |
| Prototype |
Class of object instantiated |
| Singleton |
Sole instance of a class |
| Adapter |
Interface to an object |
| Bridge |
Implementation of an object |
| Composite |
Structure/composition of an object |
| Decorator |
Responsibilities without subclassing |
| Facade |
Interface to subsystem |
| Flyweight |
Storage cost of objects |
| Proxy |
How/where object is accessed |
| Chain of Responsibility |
Object that fulfills request |
| Command |
When/how request is fulfilled |
| Interpreter |
Grammar and interpretation |
| Iterator |
How aggregate elements are accessed |
| Mediator |
How/which objects interact |
| Memento |
What private state is externalized |
| Observer |
Dependents and how they stay updated |
| State |
States of an object |
| Strategy |
Algorithm |
| Template Method |
Steps of an algorithm |
| Visitor |
Operations on object structure |
MVC mapping (canonical example)
Smalltalk MVC demonstrates three patterns working together:
| MVC piece |
Pattern |
| Model notifies Views |
Observer |
| Nested views |
Composite |
| Controller response strategy |
Strategy |
| Default controller / scrolling |
Factory Method, Decorator |
Use this when explaining publish-subscribe UI or pluggable behavior.
Lexi case study — pattern → problem (Ch 2)
| Problem |
Pattern(s) |
| Document tree structure |
Composite (recursive composition) |
| Multiple formatting policies |
Strategy |
| Embellish UI (scrollbars, borders) |
Decorator |
| Multiple look-and-feel |
Abstract Factory |
| Multiple window systems |
Bridge |
| User operations + undo |
Command |
| Spelling / hyphenation on structure |
Visitor |
Pattern comparisons (chapter discussions)
Creational
- Factory Method — easiest start; subclass proliferation risk.
- Abstract Factory — product families; large factory hierarchies.
- Prototype — clone existing instances; hide concrete classes from clients.
- Builder — step-by-step complex assembly; separate director if needed.
- Singleton — global access; prefer DI in modern code when possible.
Structural
- Adapter — retrofit compatibility. Bridge — intentional abstraction/implementation split.
- Decorator — transparent wrapper adding behavior. Proxy — access control, not feature stacking.
- Flyweight — many similar objects; extrinsic state passed in. Identity tests may lie.
Behavioral
- Strategy vs Template Method — composition/delegation vs inheritance; Strategy varies algorithm at runtime.
- State vs Strategy — State transitions are internal; Strategy chosen by client/context.
- Command vs Strategy — Command encapsulates full request + undo; Strategy is algorithm slot.
- Observer vs Mediator — Observer broadcast; Mediator centralizes interaction rules.
- Visitor vs double dispatch — add operations without changing element classes; new element types hurt Visitor.
Modern usage notes (agent)
| Pattern |
Modern note |
| Singleton |
Prefer explicit scope/DI; test doubles suffer |
| Abstract Factory |
Often replaced by DI containers + interfaces |
| Iterator |
Built into language (for, generators) — still apply concept |
| Observer |
Events, pub/sub, reactive streams — same force |
| Decorator |
Middleware, wrappers, aspect-like stacking |
| Command |
Undo stacks, job queues, CQRS commands |
| Adapter |
Anti-corruption / API clients (see domain-driven-design) |
| Facade |
Module boundaries, API gateways |
| Template Method |
Hooks vs callbacks; prefer Strategy when runtime swap needed |
| Visitor |
AST walks; switch on type smell alternative when types stable |
Functional languages: some patterns are language features (e.g. first-class functions ≈ Strategy). Still name the force being addressed.
Smells → pattern direction
| Smell |
Consider |
new ConcreteClass() everywhere |
Factory Method, Abstract Factory, Prototype |
| Giant switch on type |
State, Strategy, Visitor |
| Subclass explosion for variants |
Strategy, Decorator, Bridge |
| Two incompatible APIs |
Adapter |
| Client knows too much of subsystem |
Facade, Mediator |
| Subclass only to change one algorithm |
Strategy |
| Undo/redo missing |
Command + Memento |
UI/platform #ifdef mess |
Abstract Factory, Bridge |
| Million tiny identical objects |
Flyweight |
| Lazy load / access control |
Proxy |
| One object notifies many |
Observer |
| Complex object construction |
Builder |
First ask: Can a simpler refactor (extract function, inject dependency) suffice? YAGNI applies to patterns.
Review output format
## Design force
[What must vary or what redesign risk]
## Recommended pattern(s)
- [Name] — [one-line intent match]
## Alternatives considered
- [Pattern] — why not
## Consequences
- [Flexibility gained vs complexity/cost]
## Implementation sketch
[Domain-named roles, composition over inheritance]
Implementation checklist (before marking done)
Source
Gamma, Helm, Johnson, Vlissides — Design Patterns (Addison-Wesley, 1994). Personal skill for agent-assisted work.
1---2name: design-patterns3description: Apply Gang of Four Design Patterns (Gamma, Helm, Johnson, Vlissides) when designing, implementing, or refactoring object-oriented code. Use for pattern selection, creational/structural/behavioral design, flexibility without over-engineering, or when the user mentions design patterns, GoF, Strategy, Factory, Observer, Decorator, or Lexi case study.4---56# Design Patterns (GoF) — Agent Skill78Actionable rules distilled from *Design Patterns: Elements of Reusable Object-Oriented Software* (Gamma, Helm, Johnson, Vlissides, 1994). Patterns capture **proven designs** — not clever tricks. Apply only when the flexibility is **actually needed**.910Pair with **clean-code** for implementation quality; **domain-driven-design** when boundaries and domain models matter.1112## When to apply1314- Choosing how to structure classes/objects for change15- Refactoring toward loose coupling, composability, or pluggable behavior16- Integrating incompatible interfaces, hiding platform details, or extending without subclass explosion17- User says: design pattern, GoF, Strategy, Factory, Observer, Decorator, Adapter1819**Do not** sprinkle patterns for resume-driven design. Read **Consequences** before applying.2021---2223## Core laws (non-negotiable)24251. **Program to an interface, not an implementation** — clients depend on abstractions.262. **Favor object composition over class inheritance** — compose behavior; don't subclass for every variant.273. **Encapsulate what varies** — each pattern isolates one aspect that changes independently.284. **Delegation over inheritance** — Strategy, State, Visitor delegate to helper objects.295. **Run-time structure ≠ compile-time structure** — many patterns build dynamic object graphs (Composite, Decorator, Observer).306. **Patterns are not frameworks** — you implement them each time; they document intent and trade-offs.317. **Only apply when needed** — extra indirection has cost (complexity, performance).3233---3435## Agent workflow3637```381. PROBLEM — name the design force (what must vary? what causes redesign?)392. SELECT — match cause of redesign OR aspect to vary (Table below)403. VALIDATE — check Applicability + Consequences; consider simpler fix first414. NAME — use domain names + pattern role (e.g. TeXLayoutStrategy)425. IMPLEMENT — minimal structure; prefer composition436. VERIFY — clean-code pass; don't over-abstract44```4546**Selection order:** (1) cause of redesign → (2) intent scan → (3) related patterns graph → (4) compare patterns of same purpose.4748---4950## Two OOD principles (Ch 1)5152| Principle | Rule |53|-----------|------|54| **Program to interface** | Declare variables, parameters, returns, and attributes as abstract types (interfaces/base classes), not concrete classes. |55| **Favor composition** | Reuse by assembling objects; inheritance for true is-a specialization only. Use delegation in Strategy, State, Bridge. |5657---5859## Causes of redesign → patterns (Ch 1.6)6061| Cause | Patterns |62|-------|----------|63| Creating objects by explicit class name | Abstract Factory, Factory Method, Prototype |64| Dependence on specific operations | Chain of Responsibility, Command |65| Platform (OS/API) dependence | Abstract Factory, Bridge |66| Dependence on representation/location/implementation | Abstract Factory, Bridge, Memento, Proxy |67| Algorithmic dependencies | Builder, Iterator, Strategy, Template Method, Visitor |68| Tight coupling | Abstract Factory, Bridge, Chain of Responsibility, Command, Facade, Mediator, Observer |69| Extending by subclassing only | Bridge, Chain of Responsibility, Composite, Decorator, Observer, Strategy |70| Can't modify class conveniently | Adapter, Decorator, Visitor |7172Ask: **"What should be variable without redesign?"** — pick pattern that encapsulates that aspect.7374---7576## Pattern catalog — intents (23 patterns)7778### Creational — object creation7980| Pattern | Intent |81|---------|--------|82| **Abstract Factory** | Interface for creating *families* of related objects without specifying concrete classes |83| **Builder** | Separate construction of complex object from representation; same process → different representations |84| **Factory Method** | Interface for creating an object; *subclasses* decide which class to instantiate |85| **Prototype** | Create objects by copying a prototypical instance |86| **Singleton** | Ensure one instance + global access (use sparingly — testability cost) |8788**Choose creational:** Factory Method = subclass parameterization. Abstract Factory / Builder / Prototype = object-composition parameterization (factory object). Prototype when classes vary at runtime or cloning is costly to subclass.8990### Structural — composition & interfaces9192| Pattern | Intent |93|---------|--------|94| **Adapter** | Convert interface so incompatible classes work together (*after* design — unforeseen coupling) |95| **Bridge** | Decouple abstraction from implementation so both vary independently (*before* — known multiple impls) |96| **Composite** | Tree structures; treat individual and composite objects uniformly |97| **Decorator** | Attach responsibilities dynamically; alternative to subclassing for extension |98| **Facade** | Unified interface to a subsystem — *new* simplified interface |99| **Flyweight** | Share fine-grained objects efficiently via extrinsic state |100| **Proxy** | Surrogate controlling access (lazy load, protection, remote, caching) |101102**Adapter vs Bridge:** Adapter fixes two existing interfaces; Bridge plans multiple implementations upfront. **Adapter vs Facade:** Adapter reuses old interface; Facade defines new higher-level one. **Composite vs Decorator vs Proxy:** Similar structure; intent differs — part-whole hierarchy vs add behavior vs control access.103104### Behavioral — algorithms & responsibility105106| Pattern | Intent |107|---------|--------|108| **Chain of Responsibility** | Pass request along chain until something handles it |109| **Command** | Encapsulate request as object — parameterize, queue, log, **undo** |110| **Interpreter** | Grammar + interpreter for a small language |111| **Iterator** | Sequential access to aggregate without exposing representation |112| **Mediator** | Encapsulate how a set of objects interact — reduces explicit references |113| **Memento** | Capture/restore internal state without breaking encapsulation |114| **Observer** | One-to-many dependency; dependents notified on state change |115| **State** | Alter behavior when internal state changes — appears to change class |116| **Strategy** | Family of interchangeable algorithms encapsulated |117| **Template Method** | Algorithm skeleton in base class; subclasses override steps |118| **Visitor** | New operation on elements without changing their classes |119120**Encapsulating variation:** Strategy (algorithm), State (state-dependent behavior), Mediator (interaction protocol), Iterator (traversal). Chain of Responsibility = dynamic open-ended chain.121122---123124## Aspects you can vary (selection table)125126| Pattern | Vary independently |127|---------|-------------------|128| Abstract Factory | Families of product objects |129| Builder | How composite object is created |130| Factory Method | Subclass of object instantiated |131| Prototype | Class of object instantiated |132| Singleton | Sole instance of a class |133| Adapter | Interface to an object |134| Bridge | Implementation of an object |135| Composite | Structure/composition of an object |136| Decorator | Responsibilities without subclassing |137| Facade | Interface to subsystem |138| Flyweight | Storage cost of objects |139| Proxy | How/where object is accessed |140| Chain of Responsibility | Object that fulfills request |141| Command | When/how request is fulfilled |142| Interpreter | Grammar and interpretation |143| Iterator | How aggregate elements are accessed |144| Mediator | How/which objects interact |145| Memento | What private state is externalized |146| Observer | Dependents and how they stay updated |147| State | States of an object |148| Strategy | Algorithm |149| Template Method | Steps of an algorithm |150| Visitor | Operations on object structure |151152---153154## MVC mapping (canonical example)155156Smalltalk MVC demonstrates three patterns working together:157158| MVC piece | Pattern |159|-----------|---------|160| Model notifies Views | **Observer** |161| Nested views | **Composite** |162| Controller response strategy | **Strategy** |163| Default controller / scrolling | Factory Method, **Decorator** |164165Use this when explaining publish-subscribe UI or pluggable behavior.166167---168169## Lexi case study — pattern → problem (Ch 2)170171| Problem | Pattern(s) |172|---------|------------|173| Document tree structure | **Composite** (recursive composition) |174| Multiple formatting policies | **Strategy** |175| Embellish UI (scrollbars, borders) | **Decorator** |176| Multiple look-and-feel | **Abstract Factory** |177| Multiple window systems | **Bridge** |178| User operations + undo | **Command** |179| Spelling / hyphenation on structure | **Visitor** |180181---182183## Pattern comparisons (chapter discussions)184185### Creational186- **Factory Method** — easiest start; subclass proliferation risk.187- **Abstract Factory** — product *families*; large factory hierarchies.188- **Prototype** — clone existing instances; hide concrete classes from clients.189- **Builder** — step-by-step complex assembly; separate director if needed.190- **Singleton** — global access; prefer DI in modern code when possible.191192### Structural193- **Adapter** — retrofit compatibility. **Bridge** — intentional abstraction/implementation split.194- **Decorator** — transparent wrapper adding behavior. **Proxy** — access control, not feature stacking.195- **Flyweight** — many similar objects; extrinsic state passed in. Identity tests may lie.196197### Behavioral198- **Strategy vs Template Method** — composition/delegation vs inheritance; Strategy varies algorithm at runtime.199- **State vs Strategy** — State transitions are internal; Strategy chosen by client/context.200- **Command vs Strategy** — Command encapsulates full request + undo; Strategy is algorithm slot.201- **Observer vs Mediator** — Observer broadcast; Mediator centralizes interaction rules.202- **Visitor vs double dispatch** — add operations without changing element classes; new element types hurt Visitor.203204---205206## Modern usage notes (agent)207208| Pattern | Modern note |209|---------|-------------|210| Singleton | Prefer explicit scope/DI; test doubles suffer |211| Abstract Factory | Often replaced by DI containers + interfaces |212| Iterator | Built into language (`for`, generators) — still apply concept |213| Observer | Events, pub/sub, reactive streams — same force |214| Decorator | Middleware, wrappers, aspect-like stacking |215| Command | Undo stacks, job queues, CQRS commands |216| Adapter | Anti-corruption / API clients (see domain-driven-design) |217| Facade | Module boundaries, API gateways |218| Template Method | Hooks vs callbacks; prefer Strategy when runtime swap needed |219| Visitor | AST walks; switch on type smell alternative when types stable |220221Functional languages: some patterns are language features (e.g. first-class functions ≈ Strategy). Still name the **force** being addressed.222223---224225## Smells → pattern direction226227| Smell | Consider |228|-------|----------|229| `new ConcreteClass()` everywhere | Factory Method, Abstract Factory, Prototype |230| Giant switch on type | State, Strategy, Visitor |231| Subclass explosion for variants | Strategy, Decorator, Bridge |232| Two incompatible APIs | Adapter |233| Client knows too much of subsystem | Facade, Mediator |234| Subclass only to change one algorithm | Strategy |235| Undo/redo missing | Command + Memento |236| UI/platform `#ifdef` mess | Abstract Factory, Bridge |237| Million tiny identical objects | Flyweight |238| Lazy load / access control | Proxy |239| One object notifies many | Observer |240| Complex object construction | Builder |241242**First ask:** Can a simpler refactor (extract function, inject dependency) suffice? **YAGNI** applies to patterns.243244---245246## Review output format247248```markdown249## Design force250[What must vary or what redesign risk]251252## Recommended pattern(s)253- [Name] — [one-line intent match]254255## Alternatives considered256- [Pattern] — why not257258## Consequences259- [Flexibility gained vs complexity/cost]260261## Implementation sketch262[Domain-named roles, composition over inheritance]263```264265---266267## Implementation checklist (before marking done)268269- [ ] Pattern addresses a **real** cause of redesign or variation point270- [ ] Clients depend on **abstractions**, not concrete classes271- [ ] Composition/delegation preferred over deep inheritance272- [ ] Participant names reflect **domain** (Strategy suffix where helpful)273- [ ] Consequences accepted (indirection, object count, identity)274- [ ] Not over-applied — simpler design rejected for good reason275- [ ] **clean-code** pass on resulting structure276277---278279## Source280281Gamma, Helm, Johnson, Vlissides — *Design Patterns* (Addison-Wesley, 1994). Personal skill for agent-assisted work.