adopt-pattern
GitHub用于指导开发者从46个生产验证模式中选择并适配低层、系统或并发设计模式。通过匹配问题、验证适用性、适配代码及编写不变量测试,确保模式正确落地。
Trigger Scenarios
Install
npx skills add Totoro-jam/battle-tested-patterns --skill adopt-pattern -g -y
SKILL.md
Frontmatter
{
"name": "adopt-pattern",
"description": "Use when a developer wants to apply a low-level, systems, or concurrency design pattern in their own code, drawing on the Battle-Tested Patterns catalog of 46 production-proven patterns. Triggers three ways: they name a pattern (ring buffer, circuit breaker, actor model, LRU cache, rate limiter, trie, bloom filter, WAL, semaphore, ...); they describe a problem one solves without naming it (fixed-size buffer that overwrites the oldest entry, cascading failures across services, throttling requests, deduplicating identical strings, ordering events without wall-clock time, snapshot isolation, prefix search, set membership without storing every key, ...); or they ask which pattern fits a problem or how two related patterns differ."
}
Adopt a Pattern
Overview
The Battle-Tested Patterns catalog documents 46 patterns, each in a GitHub
source doc (URLs in the catalog below) with a When to Use / When NOT to Use /
Related Patterns decision guide, a Production Proof table of real source
links, and a multi-language Implementation. Those doc pages are the source
of truth — fetch the relevant one rather than relying on memory. This skill
routes a developer's problem to the right pattern and then drives a disciplined
adoption into their codebase; it does not reproduce the pattern content here.
Two principles do the work:
- A pattern is only worth adopting if it fits — the common failure is reaching for a named pattern that doesn't match the problem; the fit-gate catches that before any code is written.
- A pattern adopted without a durable test for its invariant is not done — a correct-looking implementation that leaves no regression test lets the invariant rot on the next edit. The verify step leaves that test behind.
When to use
- A developer names a pattern and wants it in their code.
- A developer describes a problem (see the catalog cues) without naming a pattern.
- A developer asks "which pattern fits?" or "X vs Y — which?".
When NOT to use: general feature work with no pattern in play, or a problem no catalog entry matches (say so plainly rather than forcing a fit).
Workflow
Work the four steps in order. Do not skip the fit-gate.
1. Match
Map the problem to candidate patterns using the catalog below. If the developer named a pattern, still confirm it against the cue. If a problem matches several (e.g. "throttle requests" → Rate Limiter, Semaphore, Backpressure), keep 2–3 candidates for the fit-gate.
2. Fit-gate
Fetch only the candidate patterns' doc pages (the Doc URL in the catalog)
and focus on When to Use, When NOT to Use, and Related Patterns.
- If the pattern fits, continue to step 3.
- If
When NOT to Usedescribes the developer's situation, stop and steer to the better-fit pattern named inRelated Patterns. Explain why in one or two sentences. - If nothing fits, say so. Do not adopt a pattern to satisfy the request.
Do not fetch all 46 docs. Fetch the 1–3 you are actually deciding between.
3. Adapt
Read the chosen doc's Implementation (in the developer's language) and skim
Production Proof for how real systems shape it. Then write it into their
codebase — match their naming, types, error handling, and module boundaries.
- Adapt, do not copy-paste. The reference impl is a teaching version; production code needs the project's conventions and edge-case handling.
- Carry over the invariants the doc calls out (e.g. a ring buffer's overwrite-on- full rule, a circuit breaker's half-open probe). Those are the point.
4. Verify — leave a durable invariant test
This is where adoption is won or lost: a capable agent will usually pick the right pattern and implement it correctly, then "confirm it works" with a throwaway check and move on — leaving nothing that protects the invariant on the next edit.
Write a focused test as a committed file in the developer's own project and
runner that exercises the pattern's defining behavior — use the doc's Exercises
and Challenge Questions as a checklist of cases (the boundary conditions, not
the happy path). Run it. An inline or throwaway check does not count. A pattern
adopted without a durable test for its invariant is not done.
Pattern catalog
Each row links to the pattern's doc source on GitHub — fetch it during the fit-gate. (Maintainers: this block is generated; see the skill's source repo.)
46 patterns. Match the developer's problem to a row, then fetch only that pattern's doc URL.
🧠 Data Structures
| Pattern | Reach for it when | Level | Doc URL |
|---|---|---|---|
| Bitmask | flags in one int — Pack multiple boolean flags into a single integer and manipulate them with bitwise operators for constant-time set operations. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/bitmask/index.md |
| Min Heap | priority queue — A binary tree stored in an array where the smallest element is always at the root, enabling O(1) peek and O(log n) insert/remove. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/min-heap/index.md |
| Ring Buffer | fixed-size FIFO — A fixed-size buffer that wraps around using modular arithmetic, enabling constant-time enqueue and dequeue without memory allocation. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/ring-buffer/index.md |
| Trie | prefix search — Store strings in a tree where each edge represents a character — shared prefixes share nodes, enabling O(k) lookup by key length. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/trie/index.md |
| Skip List | probabilistic order — A probabilistic sorted data structure with O(log n) search, insert, and delete — simpler to implement than balanced trees with comparable performance. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/skip-list/index.md |
| Bloom Filter | set membership — Test set membership in O(k) time with zero false negatives — at the cost of a tunable false positive rate. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/bloom-filter/index.md |
| LRU Cache | eviction policy — Evict the least recently used entry when the cache is full — O(1) get and put using a hash map plus a doubly linked list. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/lru-cache/index.md |
| B+ Tree | disk-optimized index — Self-balancing tree with high branching factor — internal nodes guide, leaf nodes store, all leaves linked for efficient range scans. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/b-plus-tree/index.md |
| Tagged Union | type-safe dispatch — Store a type tag alongside a value union so one variable safely holds different types, dispatching behavior via the tag. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/tagged-union/index.md |
| Merkle Tree | integrity proof — Hash leaves, then hash pairs upward to a root — verify any leaf's integrity in O(log n) without re-hashing the entire dataset. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/merkle-tree/index.md |
| Merge Iterator | k-way merge — Combine K sorted streams into one sorted output using a min-heap — the universal "unified view" over multiple data sources. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/merge-iterator/index.md |
⚡ Concurrency
| Pattern | Reach for it when | Level | Doc URL |
|---|---|---|---|
| Semaphore | bounded access — Limit the number of concurrent operations by maintaining a counter — acquire before work, release after, block when the limit is reached. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/semaphore/index.md |
| Actor Model | message passing — Each actor has a mailbox and processes messages sequentially — no shared state, no locks, just message passing for safe concurrency. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/actor-model/index.md |
| Work Stealing | load balance — Idle threads steal tasks from busy threads' queues — balancing load dynamically without central coordination. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/work-stealing/index.md |
| MVCC | snapshot isolation — Keep multiple timestamped versions of each value so readers never block writers — each transaction sees a consistent snapshot without locks. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/mvcc/index.md |
| Cooperative Scheduling | yield control — Break long-running work into small chunks, yielding control back to the host between each chunk to keep the system responsive. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/cooperative-scheduling/index.md |
| Double Buffering | atomic swap — Maintain two copies of state and atomically swap between them so readers always see a consistent snapshot. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/double-buffering/index.md |
| Backpressure | flow control — Slow down producers when consumers can't keep up — use bounded buffers and demand signals to prevent resource exhaustion. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/backpressure/index.md |
| Event Loop | I/O multiplexing — A single-threaded loop that multiplexes I/O via epoll/kqueue, dispatching ready events to callbacks — thousands of connections without threads. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/event-loop/index.md |
| Logical Clock | event ordering — A monotonically increasing counter that orders events without wall-clock time — enabling consistent snapshots and staleness detection. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/logical-clock/index.md |
🏗️ Systems
| Pattern | Reach for it when | Level | Doc URL |
|---|---|---|---|
| Circuit Breaker | fault tolerance — Stop calling a failing service by tracking errors and tripping open — fail fast instead of piling up timeouts. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/circuit-breaker/index.md |
| Rate Limiter | throttle — Protect services from overload by draining tokens from a bucket that refills at a fixed rate — reject requests when empty. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/rate-limiter/index.md |
| Retry Backoff | resilience — When an operation fails, retry it with progressively longer delays plus random jitter to avoid thundering herd. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/retry-backoff/index.md |
| Write-Ahead Log | durability — Log every mutation to durable storage before applying it — replay the log to recover from crashes without data loss. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/write-ahead-log/index.md |
| Batch Processing | throughput — Accumulate individual operations and execute them together as a group, amortizing per-operation overhead across the batch. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/batch-processing/index.md |
| Consistent Hashing | distribution — Distribute keys across nodes on a virtual ring so that adding or removing a node only remaps ~1/n of the keys. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/consistent-hashing/index.md |
| Dependency Graph | ordering — Model dependencies as a directed acyclic graph and topologically sort to determine a valid execution order — detecting cycles before they deadlock. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/dependency-graph/index.md |
| Middleware Chain | pipeline — Compose handlers where each wraps the next — pre-process, call next, post-process — forming a bidirectional pipeline. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/middleware-chain/index.md |
| Registry | self-register — Components register themselves into a global lookup table by name — consumers discover implementations at runtime without hardcoded dependencies. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/registry/index.md |
| Dirty Flag | deferred recompute — Mark objects as "dirty" on mutation, defer expensive recomputation until the value is actually needed, then clear the flag. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/dirty-flag/index.md |
| LSM Tree | write-optimized store — Buffer writes in memory, flush to sorted files on disk, merge files in background — trading read amplification for fast writes. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/lsm-tree/index.md |
| Checkpointing | snapshot recovery — Periodically snapshot consistent state so recovery replays only from the checkpoint — not from the beginning of time. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/checkpointing/index.md |
♻️ Memory
| Pattern | Reach for it when | Level | Doc URL |
|---|---|---|---|
| Object Pool | reuse instances — Pre-allocate a set of reusable objects to avoid the cost of repeated allocation and garbage collection on hot paths. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/object-pool/index.md |
| Flyweight | share immutables — Share identical immutable objects instead of creating duplicates, trading a lookup cost for massive memory savings when many instances have the same value. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/flyweight/index.md |
| Arena Allocator | bump alloc — Allocate objects by bumping a pointer in a pre-allocated region — free everything at once when the region is no longer needed. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/arena-allocator/index.md |
| Free List | O(1) alloc/free — Maintain a linked list of freed slots so allocation and deallocation are O(1) — reuse memory without calling the system allocator. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/free-list/index.md |
| Copy-on-Write | defer copy — Share data by reference until someone modifies it — only then make a private copy, saving memory and allocation cost for read-heavy workloads. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/copy-on-write/index.md |
| Reference Counting | auto-cleanup — Track owners via atomic counter, auto-cleanup at zero — deterministic resource lifetime without garbage collection. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/reference-counting/index.md |
| Tombstone | deferred deletion — Mark deleted entries with a tombstone marker instead of removing them — a background process reclaims space later. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/tombstone/index.md |
| Interning | deduplicate values — Deduplicate immutable values through a canonical lookup table — O(1) equality by pointer comparison instead of O(n) content comparison. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/interning/index.md |
🔄 Behavioral
| Pattern | Reach for it when | Level | Doc URL |
|---|---|---|---|
| State Machine | transitions — Model an entity's lifecycle as a set of states with explicit transitions, making impossible states unrepresentable and every state change auditable. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/state-machine/index.md |
| Observer | pub/sub — Decouple producers from consumers by letting objects subscribe to events and get notified when something happens, without the source knowing who's listening. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/observer/index.md |
| Iterator | lazy eval — Process sequences one element at a time without materializing the entire collection, enabling composable transformations with zero intermediate allocations. | beginner | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/iterator/index.md |
| Diff / Patch | minimal edits — Compare two sequences to compute the minimal set of operations (insert, delete, move) needed to transform one into the other. | intermediate | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/diff-patch/index.md |
| Vtable | manual polymorphism — Group function pointers into a struct to achieve runtime polymorphism — the manual foundation behind interfaces, traits, and virtual methods. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/vtable/index.md |
| Visitor | tree traversal dispatch — Decouple tree traversal from operations by dispatching to type-specific callbacks — enabling new operations without modifying the tree. | advanced | https://github.com/Totoro-jam/battle-tested-patterns/blob/main/docs/patterns/visitor/index.md |
Common mistakes
- Skipping the fit-gate because the developer named a pattern. Named ≠ correct
— confirm against
When NOT to Usefirst. - Copy-pasting the reference implementation verbatim. It teaches the shape; it is not drop-in production code.
- Loading many pattern docs at once. Match from the catalog cues, then open only the 1–3 candidates.
- Choosing by familiarity ("I know LRU") instead of fit. Check
Related Patterns— the better tool is often one row away. - Declaring done without a test for the pattern's invariant.
Example
Developer: "Downloads are hammering the API — I want to cap it at 5 in flight."
- Match — "cap concurrent access" → candidates: Semaphore, Rate Limiter, Backpressure.
- Fit-gate — the Semaphore doc's
When to Usedirectly lists "control access to a fixed number of resources" and "limit concurrent network requests" — a concurrency cap, which is what the developer asked for. Rate Limiter'sWhen to Usegoverns rate over time (API rate limiting, traffic shaping), a different axis. → Semaphore. - Adapt — port the doc's TypeScript semaphore into their download module,
wrapping the fetch call in
acquire()/release()with their existing error/cleanup handling so a failed download always releases its permit. - Verify — test that with the cap at 5 and 20 queued downloads, no more than 5 run concurrently and all 20 eventually complete.
Version History
- 0307be9 Current 2026-07-05 14:53


