cursor-责任链模式skill

我爱海鲸 2026-04-22 16:18:31 暂无标签

简介职责链模式、责任链模式

参考责任链模式的文章:http://www.haijin.xyz/list/article/362
可以把技能放到本机用户目录的 ~/.cursor/skills/<技能目录>/(Windows 一般是 C:\Users\你的用户名\.cursor\skills\)。这样任意项目打开后,只要 Cursor 会加载用户级 skills,就不必每个仓库复制一份。

注意~/.cursor/skills-cursor/ 是 Cursor 内置技能目录,不要把自己的技能放进去;自定义技能用 项目 .cursor/skills/ 或 用户 ~/.cursor/skills/

在项目的根目录下创建:.cursor\skills\chain-of-responsibility-expert

创建文件SKILL.md:

---
name: chain-of-responsibility-expert
description: Designs and implements Chain of Responsibility with abstract handler, concrete handlers, chain assembler, and context supporting full traversal and short-circuit. Defaults to Java; switches language on user request. Use when the user invokes /chain-of-responsibility or asks for 责任链、处理器链、拦截链、可插拔链路、审批流/权限链/过滤链重构;in this repo, align with cn.lomark.zoc.strategy (Handler, AbstractHandler, *Context, *HandlerChain).

---

# 责任链模式设计与实现专家

当用户发送 **`/chain-of-responsibility`** 或明确要按责任链编写/重构代码时,**必须**按本文输出;默认语言为 **Java**,若用户指定其他语言则整体切换(仍保持相同结构与规则)。

## 必须遵守的核心规则

1. **可运行**:给出完整包结构、可编译的类与最小依赖说明(如 Spring 可选)。
2. **必须有 Context**:承载请求数据、中间状态、最终结果;**禁止**用裸 `Map` 代替强类型上下文。
3. **两种执行语义**(须在代码中显式体现):
   - **全链路执行**:每一环都运行,除非前置已将上下文标为停止(若业务需要“全员执行”,则不设停止条件)。
   - **拦截中断**:某一环判定失败后调用 `context.stop()`(或等价机制),后续环节 **不再** 执行。
4. **开闭原则 / 可插拔**:新增环节 = 新增 Handler + 在链装配处注册顺序;**禁止**修改已有 Handler 的 `if-else` 堆砌来插入逻辑。
5. **禁止循环依赖**:Handler 只依赖接口/服务抽象;**Chain 装配类**依赖各 Handler,Handler **不得** 依赖 Chain。
6. **禁止硬编码**:业务阈值、开关、角色编码等来自配置、`@ConfigurationProperties`、枚举或注入的策略表;魔法字符串集中为常量或枚举。
7. **业务示例要求**:交付物中须包含至少三类示例之一的真实链路骨架:**权限校验链**、**审批流链**、**过滤链**(可与用户场景合并,但结构要独立可读)。

## 与本仓库(channel-platform)对齐时

参考现有形态(`cloud-fast-charging` 模块 `cn.lomark.zoc.strategy`):

- `Handler` + `AbstractHandler`:`setNext`、`handle(Request)`。
- 上下文类继承 `Request`(如 `DksRechargeContext`、`VirtualRechargeContext`)。
- `*HandlerChain`:`@PostConstruct` 中 `setNext` 串联,对外 `execute(Context)` 从第一个 handler 进入。

若当前 `AbstractHandler` **未**内置短路语义,有两种合规做法(二选一并在“模式说明”中写明):

- **A**:在子类中仅在成功路径调用 `super.handle(ctx)`;失败则 **不** 调用,实现中断。
- **B**:升级抽象层,在模板方法中统一判断 `context.isStopped()`(推荐长期维护)。

## 输出结构(固定顺序,不得省略)

对用户回复必须按以下 **六级标题** 组织(中文标题原样使用):

### 1. 模式说明

- 一句话定义责任链;说明**全链路** vs **拦截中断**在本设计中的触发条件。
- 点明与调用方的边界:谁创建 Context、谁解析最终结果。

### 2. 类设计

用表格或列表说明:`Context`、`Handler`(抽象/接口)、`ConcreteHandlers`、`Chain`(装配)、可选 `ChainResult`/枚举;说明依赖方向与扩展点。

### 3. 代码

给出 **完整** 可运行代码(包名、类名、字段、方法齐全)。至少包含:

- 上下文类(含 `stop` / `isStopped` 或等价 API,以及业务字段)。
- 抽象处理器(模板方法或显式传递 `next`)。
- ≥2 个具体处理器(其一演示**成功传递**,其一演示**中断**)。
- 链装配类(推荐 Spring `@Service` + `@PostConstruct`;非 Spring 则提供纯 Java 构造装配示例)。

### 4. 使用示例

展示调用方:构建 Context → 调用 `chain.execute(context)` → 读取结果与停止原因(若有)。

### 5. 扩展方法

说明新增一个环节的步骤清单(新建类、注入、装配顺序、配置项、单测要点);强调 **不修改** 既有 Handler 主体逻辑。

### 6. 适用场景

简述何时采用责任链;何时应改用策略模式、管道、或规则引擎(各一行对比即可)。

---

## 推荐 Java 骨架(生成代码时应贴近此结构,可按业务改名)

下列为 **canonical 模板**:上下文带短路标记;抽象类用 `final handle` 统一传递,避免遗漏 `super.handle`;链与 Handler 无环依赖。

```java
// ChainContext.java — 强类型上下文 + 短路
package com.example.chain;

public class ChainContext {
    private boolean stopped;
    private String stopReason;
    // TODO: 业务字段

    public void stop(String reason) {
        this.stopped = true;
        this.stopReason = reason;
    }
    public boolean isStopped() { return stopped; }
    public String getStopReason() { return stopReason; }
}
```

```java
// ChainHandler.java — 抽象处理器
package com.example.chain;

public abstract class ChainHandler {
    private ChainHandler next;

    public void setNext(ChainHandler next) { this.next = next; }

    public final void handle(ChainContext ctx) {
        if (ctx.isStopped()) return;
        doHandle(ctx);
        if (!ctx.isStopped() && next != null) next.handle(ctx);
    }

    protected abstract void doHandle(ChainContext ctx);
}
```

```java
// ExampleChain.java — 装配(Spring 示例)
package com.example.chain;

import jakarta.annotation.PostConstruct;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;

@Service
public class ExampleChain {
    @Resource private AuthHandler authHandler;
    @Resource private ApprovalHandler approvalHandler;
    @Resource private FilterHandler filterHandler;

    @PostConstruct
    void wire() {
        authHandler.setNext(approvalHandler);
        approvalHandler.setNext(filterHandler);
    }

    public void execute(ChainContext ctx) {
        authHandler.handle(ctx);
    }
}
```

**权限校验 / 审批流 / 过滤链** 三类示例:将 `AuthHandler`、`ApprovalHandler`、`FilterHandler` 替换为对应业务命名,在 `doHandle` 中读取配置或仓储,失败时 `ctx.stop("...")`。

更多 **可编译的完整串联示例**(权限 → 审批 → 过滤,含配置类与 `main`):见 [examples.md](examples.md)。

---

## 自检清单(输出前在思考中完成)

- [ ] Context 是否为强类型且持有最终结果?
- [ ] 是否同时演示了“全链路”和“拦截中断”路径(可用注释 + 两个调用示例说明)?
- [ ] 是否存在 Handler → Chain 的反向依赖或包间环?
- [ ] 是否消除了魔法字符串与硬编码阈值?
- [ ] 六级输出结构是否齐全?

---

## 反例(禁止)

- 在单个 `handle` 方法内用长 `if-else` 模拟多段责任(应拆类)。
- `HandlerA` 注入 `HandlerB`,同时 `HandlerB` 注入 `HandlerA`。
- 链顺序写死在业务 Service 的多处复制粘贴(应唯一装配点)。

examples.md:

# 责任链完整示例(权限 → 审批 → 过滤)

可作为 `/chain-of-responsibility` 生成代码时的参照;包名 `com.example.workflow` 可按项目修改。

## OrderWorkflowContext.java

```java
package com.example.workflow;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class OrderWorkflowContext {
    private boolean stopped;
    private String stopReason;

    private String userId;
    private List<String> roles = new ArrayList<>();
    private int orderAmountFen;
    private String region;
    private boolean approved;
    private final List<String> auditTrail = new ArrayList<>();

    public void stop(String reason) {
        this.stopped = true;
        this.stopReason = reason;
    }

    public boolean isStopped() { return stopped; }
    public String getStopReason() { return stopReason; }

    public String getUserId() { return userId; }
    public void setUserId(String userId) { this.userId = userId; }

    public List<String> getRoles() { return Collections.unmodifiableList(roles); }
    public void setRoles(List<String> roles) { this.roles = new ArrayList<>(roles); }

    public int getOrderAmountFen() { return orderAmountFen; }
    public void setOrderAmountFen(int orderAmountFen) { this.orderAmountFen = orderAmountFen; }

    public String getRegion() { return region; }
    public void setRegion(String region) { this.region = region; }

    public boolean isApproved() { return approved; }
    public void setApproved(boolean approved) { this.approved = approved; }

    public List<String> getAuditTrail() { return Collections.unmodifiableList(auditTrail); }
    public void trace(String line) { this.auditTrail.add(line); }
}
```

## WorkflowHandler.java

```java
package com.example.workflow;

public abstract class WorkflowHandler {
    private WorkflowHandler next;

    public void setNext(WorkflowHandler next) { this.next = next; }

    public final void handle(OrderWorkflowContext ctx) {
        if (ctx.isStopped()) return;
        doHandle(ctx);
        if (!ctx.isStopped() && next != null) next.handle(ctx);
    }

    protected abstract void doHandle(OrderWorkflowContext ctx);
}
```

## PermissionCheckHandler.java(权限校验 · 可中断)

```java
package com.example.workflow;

import java.util.Objects;
import java.util.Set;

public class PermissionCheckHandler extends WorkflowHandler {

    private final Set<String> blockedRegions;
    private final String requiredRole;

    public PermissionCheckHandler(Set<String> blockedRegions, String requiredRole) {
        this.blockedRegions = Objects.requireNonNull(blockedRegions);
        this.requiredRole = Objects.requireNonNull(requiredRole);
    }

    @Override
    protected void doHandle(OrderWorkflowContext ctx) {
        ctx.trace("Permission: check roles and region");
        boolean hasRole = ctx.getRoles().stream().anyMatch(requiredRole::equals);
        if (!hasRole) {
            ctx.stop("缺少角色: " + requiredRole);
            return;
        }
        if (ctx.getRegion() != null && blockedRegions.contains(ctx.getRegion())) {
            ctx.stop("地区禁止下单: " + ctx.getRegion());
        }
    }
}
```

## ApprovalHandler.java(审批流 · 大额需审批)

```java
package com.example.workflow;

public class ApprovalHandler extends WorkflowHandler {

    private final int approvalThresholdFen;

    public ApprovalHandler(int approvalThresholdFen) {
        this.approvalThresholdFen = approvalThresholdFen;
    }

    @Override
    protected void doHandle(OrderWorkflowContext ctx) {
        ctx.trace("Approval: threshold=" + approvalThresholdFen);
        if (ctx.getOrderAmountFen() >= approvalThresholdFen && !ctx.isApproved()) {
            ctx.stop("大额订单需审批通过");
            return;
        }
        ctx.trace("Approval: passed");
    }
}
```

## RegionFilterHandler.java(过滤链 · 全链路尾部记录)

```java
package com.example.workflow;

public class RegionFilterHandler extends WorkflowHandler {

    @Override
    protected void doHandle(OrderWorkflowContext ctx) {
        ctx.trace("Filter: region=" + ctx.getRegion());
        // 示例:仅追加审计信息,不中断
    }
}
```

## OrderWorkflowChain.java(装配)

```java
package com.example.workflow;

import java.util.Set;

public class OrderWorkflowChain {

    private final WorkflowHandler head;

    public OrderWorkflowChain(WorkflowProperties props) {
        PermissionCheckHandler p = new PermissionCheckHandler(
                Set.copyOf(props.getBlockedRegions()),
                props.getRequiredRole());
        ApprovalHandler a = new ApprovalHandler(props.getApprovalThresholdFen());
        RegionFilterHandler f = new RegionFilterHandler();
        p.setNext(a);
        a.setNext(f);
        this.head = p;
    }

    public void execute(OrderWorkflowContext ctx) {
        head.handle(ctx);
    }
}
```

## WorkflowProperties.java(避免硬编码)

```java
package com.example.workflow;

import java.util.ArrayList;
import java.util.List;

public class WorkflowProperties {
    private List<String> blockedRegions = new ArrayList<>();
    private String requiredRole = "BUYER";
    private int approvalThresholdFen = 100_000;

    public List<String> getBlockedRegions() { return blockedRegions; }
    public void setBlockedRegions(List<String> blockedRegions) { this.blockedRegions = blockedRegions; }

    public String getRequiredRole() { return requiredRole; }
    public void setRequiredRole(String requiredRole) { this.requiredRole = requiredRole; }

    public int getApprovalThresholdFen() { return approvalThresholdFen; }
    public void setApprovalThresholdFen(int approvalThresholdFen) { this.approvalThresholdFen = approvalThresholdFen; }
}
```

## DemoMain.java(使用示例)

```java
package com.example.workflow;

import java.util.List;

public class DemoMain {
    public static void main(String[] args) {
        WorkflowProperties props = new WorkflowProperties();
        props.setBlockedRegions(List.of("XX"));
        props.setRequiredRole("BUYER");
        props.setApprovalThresholdFen(50_000);

        OrderWorkflowChain chain = new OrderWorkflowChain(props);

        OrderWorkflowContext ok = new OrderWorkflowContext();
        ok.setUserId("u1");
        ok.setRoles(List.of("BUYER"));
        ok.setOrderAmountFen(10_000);
        ok.setRegion("SH");
        ok.setApproved(false);

        chain.execute(ok);
        System.out.println("stopped=" + ok.isStopped() + " reason=" + ok.getStopReason());
        System.out.println(ok.getAuditTrail());

        OrderWorkflowContext denied = new OrderWorkflowContext();
        denied.setUserId("u2");
        denied.setRoles(List.of("GUEST"));
        denied.setOrderAmountFen(10_000);
        chain.execute(denied);
        System.out.println("stopped=" + denied.isStopped() + " reason=" + denied.getStopReason());
    }
}
```

说明:`PermissionCheckHandler` 演示 **拦截**;`ApprovalHandler` 演示 **条件中断**;`RegionFilterHandler` 演示 **全链路尾部环节**。配置通过 `WorkflowProperties` 注入,避免魔法数。

你好:我的2025