↑ ↓ 移动 · Enter 打开 · Esc 关闭点按一个结果

架构
skill · build 类 · opus

gof-design-patterns

根据能说明其必要性的症状,在 Java 和 Spring 中选择并实现一种设计模式。

skill · buildopus2 允许的路径随生成的项目导出
§ skill 的定义

gof-design-patterns,逐节说明

skill 自己的 SKILL.md 的各个章节,节选。悬停或点击一个章节,查看它引用的项目规则、模板和 references/ 文件。章节也是标签:点击即可跳转。

nerviz/.claude/skills/gof-design-patterns/SKILL.md

## Why this is a skill and not a rule

A pattern is not a rule. A rule says *always*; a pattern says *when*. That's why this is a skill and not rules/ — it only costs context when invoked. Form 2 (manual invocation) and not Form 1, because a catalog the model reaches on its own turns into a pattern applied without the symptom that justifies it, which is what the entry rule below exists to stop.

Entry rule: no pattern without a symptom observed in the code, or a force the approved spec already names. Applying a pattern preemptively is overengineering — a Factory for two lines, a Strategy for a single if, an interface with one implementation that will never have a second. A force named in the spec is not preemption: variants or rules the spec enumerates, a cross-cutting concern it applies over several implementations, construction it constrains with invariants, a predicate it uses both to decide and to query — code written from that spec would show the symptom on its first version, and choosing the pattern before writing it is how that first version is never written badly. The "When not" column binds either way. If you can point neither to the file and line that hurts nor to the spec line that names the force, the answer is "apply no pattern at all".

Pinned to opus: choosing a pattern against a growing chain is judgment, and the pin only raises the model for the rest of the turn (@.claude/decisions/0081-skill-model-required-per-class.md).

## Procedure

  1. Name the symptom in the actual code (file:line), or the force in the approved spec
  2. Look up the symptom in the table. No matching row, stop — write simple code.
  3. Confirm the pattern doesn't collide with the active blueprint's packages.map.
  4. Generate from the exemplar in templates/, with the names from
  5. Record it in an ADR if the pattern changes the shape of an entire module.

## Catalog

Symptom in codePatternWhen not
switch/if-else over a type or enum, repeated in ≥ 2 places, growing with each new ruleStrategyTwo stable branches that have never grown · the branch needs nothing outside the value — a method of the enum or sealed type · a closed set one layer branches on once — a switch expression there; both per @.claude/rules/code-quality.md § Branching on a closed set
Construction with invariants, many steps, or possible invalid combinationsStatic factory (of, from)A record with validation in the compact constructor is already enough
≥ 4 optional constructor parametersBuilderRecord + with*; Lombok @Builder on a domain object hides invariants
Cross-cutting behavior (retry, audit) repeated across implementationsDecoratorA Spring aspect already exists (@Transactional, @Retryable) that does the same thing — or the behavior is a cache, whose decorator shape @.claude/rules/caching.md owns
Business predicate duplicated between service and querySpecificationPredicate used only once
Output adapter with multiple technologies (JPA + external REST) behind the same portAdapter (already the blueprint)A single technology — the port is enough
Aggregate that emits ≥ 2 events consumed by several modulesDomain EventsA single consumer in the same module — direct call

This table is the enforceable subset: seven rows, each with a symptom threshold and a "when not" column. For a symptom that doesn't match any row above, references/pattern-catalog.md covers the full GoF catalog — every pattern on <https://refactoring.guru/design-patterns/java>, each with a shape reference in templates/ and this repo's verdict on the ones that don't (forbidden, or already covered by the language/framework). It's triage, not a second menu: the entry rule below still gates every row in it the same way it gates the seven here — an exemplar existing is not permission to apply it without a real symptom.

## Design-time use

A pattern creates classes and interfaces, so when it is chosen decides whether the approved spec shows the code's real shape. Chosen by the executor after approval, it never does. So every design skill of the /new-feature pipeline runs this check for its own layer, before writing its partial, and records the answer there — the layer that owns the classes owns the pattern that shapes them. This section is read, never invoked: a design run cannot reach a build-class skill, and it needs no writer here.

  1. Forces in the spec. Read the lines of 00-use-case.md and of the upstream partials
  2. Symptoms on disk. The layer's existing code, already surveyed by the skill's own
  3. Match against § Catalog, then references/pattern-catalog.md for what no row covers.
  4. Write the ## Design patterns section of the partial — always present, one row per

    … 此处截断,其余见文件

    ## Forbidden in this repository

    • Singleton — the Spring container already gives singleton scope; the manual version
    • Service Locator / ApplicationContext.getBean — violates the composition set in
    • Impl suffix, always — @.claude/rules/naming.md: the name says the role, not
    • Pattern name standing in for a role name that exists (OrderStrategy instead of
    在 GitHub 上打开完整文件 →
    § 行为

    它读什么、写什么、拒绝什么

    skill 自己的契约,取自 SKILL.md,保留原文。

    Class

    build — the territory is skill_classes.build's override for this skill in @.claude/schemas/extensions.json: the src/ tree, nothing else. It sits in build rather than with the design skills because it materializes Java code, and ArchHook.java guard therefore also makes it unreachable from inside a design run.

    Reads

    .claude/rules/code-quality.md, .claude/rules/naming.md, .claude/rules/architecture-ddd.md, the active blueprint's packages.map, and references/pattern-catalog.md when the symptom doesn't match any row of the curated table above.

    Writes

    domain and application code in the generated project. Doesn't touch the inbound REST adapter — the package the blueprint's packages.map assigns to that role, whether adapter.in.rest or infrastructure.rest — which is rest-api-architect's territory.

    Three uses, one writer each

    Design time — the pipeline's design skills read § Design-time use and write the decision into their own partial; this skill writes nothing and is not invoked (@.claude/decisions/0089-design-patterns-decided-at-design-time.md). Standalone — a human runs /gof-design-patterns against real code with an observed symptom; this skill is the sole writer for that turn, as above. Injected — in a generated project, ArchHook.java context subagent runs at SubagentStart and hands the sections listed in subagent_context of @.claude/schemas/extensions.json (this file's ## Why this is a skill and not a rule, ## Catalog and ## Forbidden in this repository) to every agent whose agent_classes entry declares pattern_catalog: true, before its first turn. The agent implements the patterns the spec already decided, and applies a row on its own only for a symptom already on disk, never as a separate invocation. In that mode this skill writes nothing itself: the agent remains the sole owner of src/** (invariant 2), and the catalog is reference material, the same role templates/*.example plays for the other four pipeline skills. Renaming one of those three headings empties the injection — ArchHook.java schema fails on it by name. @.claude/decisions/0077-pattern-catalog-injected-at-subagent-start.md, which supersedes 0025: a skill with disable-model-invocation: true cannot be preloaded through an agent's skills: field, so the catalog 0025 described never arrived.

    Doesn't collide with the design skills

    (domain-modeling, persistence-architect, rest-api-architect, messaging-architect, jobs-architect, cache-architect). They own the pattern decision for a use case being designed, each for its own layer, through § Design-time use; this skill owns the catalog and, invoked standalone, refactors code that already exists and already hurts, from a concrete file:line, outside any feature run.

    Does not

    create rules. If a new limit has to always hold, it goes to rules/code-quality.md, not here.

    来源:SKILL.md § Contract(nerviz e4cae27)。

    § guard 与 hook

    guard 如何处理它

    build 是这个 skill 的类别,左侧的列表就是它的领地。skill 在自己的提示上运行时阶段打开,ArchHook 对照这份列表判断每一次写入。右侧的文字是 hook 自己输出的。

    gof-design-patterns 的 write_allow

    • ✓src/**
    • ✓**/src/**
    • 当 skill 自己打开阶段时,此列表之外的任何路径

    拒绝以退出码 2 结束,消息回到模型。

    > /gof-design-patterns …
    UserPromptSubmit
      guard prompt                     exit 0
    # phase opened: gof-design-patterns (class build)
    # write_allow: src/**, **/src/**
    
    § 如何被调用

    由谁调用

    它不是某条链上的步骤。它由自己的提示 /gof-design-patterns 启动,guard 像对待其他 skill 一样对待它:阶段打开,其类别的领地生效。

    ← 返回链路