agentleFS
kayamankayaman/skills/design-patterns/SKILL.md

design-patterns

Skill3 starsChanged 8 months agoCC0-1.0View on GitHub

Enforces correct application of software design patterns including all 23 Gang of Four patterns and modern additions. Use when selecting a creational, structural, or behavioral pattern, evaluating whether a pattern is appropriate, refactoring toward patterns, reviewing code for pattern-itis or over-engineering, or deciding between pattern-based and language-native solutions.

33 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use logging-patterns, tdd-rust and 8 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • DIL8654Skill

    logging-patterns

    Keep logs structured, correlated, low-noise, and safe for production support. Use when adding operational logging, reviewing observability, or improving diagnostics in .NET services.

    Also in 7 projects that use this

  • FlorianBruniauxSkill

    tdd-rust

    Also in 3 projects that use this

  • mstuder-slalomSkill

    jpa-patterns

    JPA/Hibernate patterns for entity design, relationships, query optimization, transactions, auditing, indexing, pagination, and pooling in Spring Boot.

    Also in 6 projects that use this

  • ufodev-ioSkill

    security-guardian

    Comprehensive security layer for all interactions with Claude: audits code, dependencies, commands, configs, and AI-generated output for vulnerabilities. Protects against prompt injection, data leaks, unsafe advice, and social engineering. Works in Cursor, Claude Code, claude.ai, and API contexts. Use always as a background security protocol in any Claude-powered environment.

    Also in 3 projects that use this

  • DIL8654Skill

    api-contract-review

    Review ASP.NET Core Web API contracts for HTTP semantics, versioning, backward compatibility, and response consistency. Use when the user asks to review an API, check endpoints, validate REST behavior, or before releasing contract changes.

    Also in 3 projects that use this

  • zavierSkill

    java-code-review

    Java代码审查技能,通过比较两个git分支进行自动化代码审查

    Also in 3 projects that use this

The file

Show its rules and text

We split this skill into the rules it gives an agent

18 rules. 0 are common, 18 are distinctive, and 0 are very specific to this project.

  • 0

    Common

    Most of the 32 edited versions we read keep these.

  • 18

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every pattern decision MUST be guided by these two principles:

    line 22
  2. Distinctive:

    MUST NOT use Singleton in new code — use dependency injection to manage single-instance lifecycle externally

    line 41
  3. Distinctive:

    SHOULD prefer Builder over telescoping constructors when an object has 4+ configuration options

    line 42
  4. Distinctive:

    SHOULD use Factory Method or Abstract Factory when the concrete type is a decision that should be deferred

    line 43
  5. Distinctive:

    SHOULD use Adapter as the primary pattern for integrating external systems

    line 61
  6. Distinctive:

    SHOULD prefer Decorator over inheritance for optional, combinable behavior

    line 62
  7. Distinctive:

    MUST separate intrinsic (shared) from extrinsic (contextual) state when applying Flyweight

    line 63
  8. Distinctive:

    SHOULD prefer Strategy over Template Method — composition over inheritance

    line 85
  9. Distinctive:

    SHOULD use language-native constructs (iterators, lambdas, reactive streams) before implementing Iterator, Strategy, or Observer manually

    line 86
  10. Distinctive:

    MUST evaluate whether the pattern adds value beyond what the language provides natively

    line 87
  11. Distinctive:

    MUST NOT apply a pattern when only one implementation exists and no variation is foreseeable

    line 107
  12. Distinctive:

    MUST NOT use a pattern the team does not understand — it becomes accidental complexity

    line 108
  13. Distinctive:

    SHOULD NOT apply patterns preemptively — refactor *toward* patterns when complexity emerges (Kerievsky)

    line 109
  14. Distinctive:

    SHOULD start with the simplest thing that works.

    line 110
  15. Distinctive:

    Check if a language feature solves it natively (generics, lambdas, protocols, pattern matching)

    line 117
  16. Distinctive:

    If not, select the pattern whose intent matches the problem

    line 118
  17. Distinctive:

    Verify the pattern improves readability and maintainability for the team

    line 120
  18. Distinctive:

    Before applying or recommending a pattern, verify:

    line 126

“Common” is measured: kept by at least 6 in 10 of the 32 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Design Patterns

Reference: Design Patterns (GoF), Head First Design Patterns (Freeman & Robson), Refactoring to Patterns (Kerievsky)

When to Apply

  • Selecting a pattern for a recurring design problem
  • Refactoring code that exhibits a known code smell toward a pattern
  • Reviewing whether an applied pattern is justified or over-engineered
  • Deciding if a language feature (lambdas, protocols, generics) eliminates the need for a pattern
  • Communicating design intent using shared pattern vocabulary

The Two GoF Maxims

Every pattern decision MUST be guided by these two principles:

  1. Program to an interface, not an implementation — depend on abstractions; swap implementations without changing clients
  2. Favor object composition over class inheritance — assemble behavior from collaborating objects rather than building class trees

Creational Patterns

Select based on what varies in object creation:

PatternIntentUse WhenAvoid When
Abstract FactoryCreate families of related objects without specifying concrete classesMultiple product families must be interchangeable (e.g., UI themes, platform adapters)Only one product family exists
BuilderSeparate construction of complex objects from representationObject has many optional parameters or multi-step constructionConstructor with 1–3 required params suffices
Factory MethodLet subclasses decide which class to instantiateThe exact type depends on runtime context or configurationA simple constructor call is clear enough
PrototypeCreate objects by cloning an existing instanceCreating from scratch is expensive or involves complex setupObject graphs are simple and cheap to construct
SingletonEnsure one instance with global accessAlmost never — prefer DI container-managed lifecycleTesting, concurrency, or coupling matter (most cases)
  • MUST NOT use Singleton in new code — use dependency injection to manage single-instance lifecycle externally
  • SHOULD prefer Builder over telescoping constructors when an object has 4+ configuration options
  • SHOULD use Factory Method or Abstract Factory when the concrete type is a decision that should be deferred

Structural Patterns

Select based on how objects and classes are composed:

PatternIntentUse WhenAvoid When
AdapterConvert an incompatible interface into one clients expectIntegrating third-party code or legacy systemsYou control both interfaces and can change one
BridgeDecouple abstraction from implementation so both vary independentlyTwo orthogonal dimensions of variation (e.g., shape × renderer)Only one dimension varies
CompositeTreat individual objects and compositions uniformly as a treeRecursive part-whole hierarchies (file systems, UI components, org charts)The structure is flat, not tree-shaped
DecoratorAttach behavior dynamically without subclassingAdding optional, combinable responsibilities at runtimeBehavior is always required — just put it in the class
FacadeSimplified interface to a complex subsystemClients need a streamlined entry point; subsystem internals should be hiddenThe subsystem is already simple
FlyweightShare fine-grained objects to save memoryThousands of similar objects with shared intrinsic stateObject count is small; optimization is premature
ProxySurrogate controlling access (lazy loading, caching, protection, remote)Access control, expensive initialization, or cross-network accessDirect access has no cost or risk
  • SHOULD use Adapter as the primary pattern for integrating external systems
  • SHOULD prefer Decorator over inheritance for optional, combinable behavior
  • MUST separate intrinsic (shared) from extrinsic (contextual) state when applying Flyweight

Behavioral Patterns

Select based on how objects communicate and assign responsibility:

PatternIntentUse WhenAvoid When
Chain of ResponsibilityPass request along a chain until handledMiddleware pipelines, event processing, validation chainsA single handler always processes the request
CommandEncapsulate a request as an objectUndo/redo, queuing, logging, transaction replayThe action is simple and needs no history
InterpreterDefine grammar and interpret sentencesSmall, domain-specific languages (query filters, rules engines)The grammar is complex — use a parser generator
IteratorSequential access without exposing internalsBuilt into virtually all modern languages — rarely implement manuallyLanguage-native iteration exists
MediatorCentralize complex inter-object communicationMany objects with complex, many-to-many interactionsObjects have simple, direct relationships
MementoCapture and restore state without breaking encapsulationUndo, snapshots, time-travel debuggingState is trivial to reconstruct
ObserverNotify dependents when state changesEvent-driven systems, reactive UI, pub-subUse framework-native reactive patterns (RxJS, signals, hooks)
StateAlter behavior when internal state changesObject behaves differently in distinct states with defined transitionsA simple if/else on one flag suffices
StrategyInterchangeable algorithm familyMultiple algorithms for the same task, selected at runtimeIn FP languages, just pass a lambda/function
Template MethodAlgorithm skeleton with overridable stepsFixed workflow with varying steps across subclassesComposition with Strategy achieves the same without inheritance
VisitorAdd operations to elements without modifying their classesNew operations are frequent; element types are stableElement hierarchy changes often — every Visitor breaks
  • SHOULD prefer Strategy over Template Method — composition over inheritance
  • SHOULD use language-native constructs (iterators, lambdas, reactive streams) before implementing Iterator, Strategy, or Observer manually
  • MUST evaluate whether the pattern adds value beyond what the language provides natively

Modern Patterns Beyond GoF

PatternIntentContext
Dependency InjectionSupply dependencies externally rather than creating them internallyEnables testing, decoupling, and DIP compliance
Null ObjectProvide a no-op implementation instead of null checksEliminates if (x != null) scattered through code
RepositoryCollection-like interface for aggregate persistenceDDD — one repository per aggregate root
Unit of WorkCoordinate writes across repositories in a single transactionEnsuring consistency across multiple aggregates
SpecificationComposable, reusable business rule objectsComplex query/validation logic that must be combined

When NOT to Use Patterns

Pattern-itis — applying patterns speculatively — is worse than the problems patterns solve.

  • MUST NOT apply a pattern when only one implementation exists and no variation is foreseeable
  • MUST NOT use a pattern the team does not understand — it becomes accidental complexity
  • SHOULD NOT apply patterns preemptively — refactor toward patterns when complexity emerges (Kerievsky)
  • SHOULD start with the simplest thing that works; introduce a pattern when the code smell appears

Norvig's observation: 16 of 23 GoF patterns are simplified or eliminated by dynamic language features. Before applying a pattern, ask: "Does my language already solve this?"

Decision Flow

  1. Identify the specific code smell or design problem
  2. Check if a language feature solves it natively (generics, lambdas, protocols, pattern matching)
  3. If not, select the pattern whose intent matches the problem
  4. Apply the simplest form of the pattern — avoid gold-plating
  5. Verify the pattern improves readability and maintainability for the team

Checklist

Before applying or recommending a pattern, verify:

  • A specific, recurring problem has been identified (not speculative future need)
  • Language-native features have been considered first
  • The selected pattern's intent matches the actual problem
  • The pattern improves — not hinders — code readability for the team
  • Singleton is NOT used (DI container manages lifecycle instead)
  • Composition-based patterns are preferred over inheritance-based ones
  • The pattern is applied in its simplest form without unnecessary abstraction layers
  • The code compiles and passes tests after applying the pattern

Key References

BookAuthor(s)PublisherYear
Design Patterns: Elements of Reusable OO SoftwareGamma, Helm, Johnson, VlissidesAddison-Wesley1994
Head First Design Patterns (2nd ed.)Freeman & RobsonO'Reilly2021
Patterns of Enterprise Application ArchitectureMartin FowlerAddison-Wesley2002
Refactoring to PatternsJoshua KerievskyAddison-Wesley2004
Dive Into Design PatternsAlexander ShvetsRefactoring.Guru2021
Game Programming PatternsRobert NystromGenever Benning2014
Fundamentals of Software ArchitectureMark Richards, Neal FordO'Reilly2020
Software Architecture: The Hard PartsFord, Richards, Sadalage, DehghaniO'Reilly2021

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.