TypeScript设计模式:责任链模式

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,允许将请求沿处理者链传递,直到某个处理者处理请求或链结束为止。

设计模式原理

责任链模式通过构建一个处理者链,允许请求在链中传递,每个处理者决定是否处理请求或传递给下一个处理者。在工作流引擎中,责任链模式适合处理需要多级审批或条件判断的场景(如审批金额、验证权限),通过泛型节点确保类型安全,动态构建处理链。

责任链模式的结构

  1. Handler(处理者接口) :定义处理请求的方法和设置下一个处理者的方法。
  2. ConcreteHandler(具体处理者) :实现处理逻辑,决定是否处理或传递请求。
  3. Client(客户端) :通过 JSON 配置创建处理链并发起请求。

优点

  • 解耦性:请求发送者与处理者解耦,客户端无需知道具体处理者。
  • 灵活性:动态调整处理链顺序或添加新处理者。
  • 类型安全:结合泛型节点,确保请求和处理逻辑的参数类型匹配。
  • 可扩展性:新增处理者只需实现新节点,无需修改现有代码。

适用场景

  • 需要多级处理请求(如工作流中的审批、验证、日志记录)。
  • 处理者顺序或逻辑动态变化。
  • 希望通过声明式配置(如 JSON)定义处理链。

TypeScript 实现示例

以下示例在工作流引擎中使用泛型节点 GenericNode<T>,通过责任链模式实现审批流程。客户端通过 JSON 配置定义处理链(如初级审批 → 高级审批),每个节点决定是否处理请求或传递给下一个节点。

typescript 复制代码
// 节点类型枚举
enum NodeType {
    APPROVAL = 'approval',
    VALIDATION = 'validation',
    LOGGING = 'logging'
}

// JSON 节点配置接口
interface NodeConfigJson<T = any> {
    type: NodeType;
    params: T & { id: string };
}

// 请求参数类型
interface ApprovalRequest {
    amount: number;
    user: string;
}

// 节点参数类型
interface ApprovalParams { id: string; level: string; threshold: number }
interface ValidationParams { id: string; requiredRole: string }
interface LoggingParams { id: string; logLevel: string }

// 泛型节点接口(处理者接口)
interface WorkflowNode<T> {
    type: NodeType;
    params: T;
    setNext(next: WorkflowNode<any>): void;
    handle(request: ApprovalRequest): string;
    getDetails(): string;
}

// 泛型节点实现
class GenericNode<T> implements WorkflowNode<T> {
    private next: WorkflowNode<any> | null = null;

    constructor(public type: NodeType, public params: T) {}

    setNext(next: WorkflowNode<any>): void {
        this.next = next;
    }

    handle(request: ApprovalRequest): string {
        switch (this.type) {
            case NodeType.APPROVAL:
                const approvalParams = this.params as ApprovalParams;
                if (request.amount <= approvalParams.threshold) {
                    return `审批节点(ID: ${approvalParams.id}, 级别: ${approvalParams.level}):批准金额 ${request.amount}`;
                }
                return this.passToNext(request, `审批节点(ID: ${approvalParams.id}):金额 ${request.amount} 超出权限`);
            case NodeType.VALIDATION:
                const validationParams = this.params as ValidationParams;
                if (request.user === validationParams.requiredRole) {
                    return `验证节点(ID: ${validationParams.id}):用户 ${request.user} 权限验证通过`;
                }
                return this.passToNext(request, `验证节点(ID: ${validationParams.id}):用户 ${request.user} 权限不足`);
            case NodeType.LOGGING:
                const loggingParams = this.params as LoggingParams;
                const logMessage = `日志节点(ID: ${loggingParams.id}, 级别: ${loggingParams.logLevel}):记录请求 ${JSON.stringify(request)}`;
                return this.next ? `${logMessage}\n${this.next.handle(request)}` : logMessage;
            default:
                return `未知节点类型:${this.type}`;
        }
    }

    private passToNext(request: ApprovalRequest, message: string): string {
        if (this.next) {
            return `${message}\n${this.next.handle(request)}`;
        }
        return `${message}\n未处理:无后续节点`;
    }

    getDetails(): string {
        return `详情:${this.type} 节点,ID=${this.params.id}, 参数=${JSON.stringify(this.params)}`;
    }
}

// 工厂类:创建节点
class WorkflowNodeFactory {
    createNode<T>(config: NodeConfigJson<T>): WorkflowNode<T> {
        return new GenericNode<T>(config.type, config.params);
    }
}

// 客户端代码:构建处理链并处理请求
function processWorkflow(factory: WorkflowNodeFactory, nodes: NodeConfigJson[], request: ApprovalRequest) {
    const workflowNodes = nodes.map(config => factory.createNode(config));

    // 构建责任链
    for (let i = 0; i < workflowNodes.length - 1; i++) {
        workflowNodes[i].setNext(workflowNodes[i + 1]);
    }

    // 输出节点详情
    console.log("=== 责任链详情 ===");
    workflowNodes.forEach((node, index) => {
        console.log(`节点 ${index + 1} 详情:${node.getDetails()}`);
    });

    // 处理请求
    console.log("\n=== 处理请求 ===");
    const result = workflowNodes[0].handle(request);
    console.log(result);
}

// 测试代码
function main() {
    // JSON 配置:初级审批 → 高级审批 → 日志记录
    const workflowNodes: NodeConfigJson[] = [
        {
            type: NodeType.APPROVAL,
            params: { id: "APP001", level: "初级", threshold: 1000 }
        },
        {
            type: NodeType.APPROVAL,
            params: { id: "APP002", level: "高级", threshold: 5000 }
        },
        {
            type: NodeType.LOGGING,
            params: { id: "LOG001", logLevel: "INFO" }
        }
    ];

    // 测试请求
    const request1: ApprovalRequest = { amount: 800, user: "manager" };
    const request2: ApprovalRequest = { amount: 2000, user: "manager" };

    console.log("工作流:初级审批 → 高级审批 → 日志记录");
    const factory = new WorkflowNodeFactory();

    console.log("\n=== 测试请求1(金额800) ===");
    processWorkflow(factory, workflowNodes, request1);

    console.log("\n=== 测试请求2(金额2000) ===");
    processWorkflow(factory, workflowNodes, request2);
}

main();

运行结果

ini 复制代码
工作流:初级审批 → 高级审批 → 日志记录

=== 测试请求1(金额800) ===
=== 责任链详情 ===
节点 1 详情:详情:approval 节点,ID=APP001, 参数={"id":"APP001","level":"初级","threshold":1000}
节点 2 详情:详情:approval 节点,ID=APP002, 参数={"id":"APP002","level":"高级","threshold":5000}
节点 3 详情:详情:logging 节点,ID=LOG001, 参数={"id":"LOG001","logLevel":"INFO"}

=== 处理请求 ===
审批节点(ID: APP001, 级别: 初级):批准金额 800
日志节点(ID: LOG001, 级别: INFO):记录请求 {"amount":800,"user":"manager"}

=== 测试请求2(金额2000) ===
=== 责任链详情 ===
节点 1 详情:详情:approval 节点,ID=APP001, 参数={"id":"APP001","level":"初级","threshold":1000}
节点 2 详情:详情:approval 节点,ID=APP002, 参数={"id":"APP002","level":"高级","threshold":5000}
节点 3 详情:详情:logging 节点,ID=LOG001, 参数={"id":"LOG001","logLevel":"INFO"}

=== 处理请求 ===
审批节点(ID: APP001):金额 2000 超出权限
审批节点(ID: APP002, 级别: 高级):批准金额 2000
日志节点(ID: LOG001, 级别: INFO):记录请求 {"amount":2000,"user":"manager"}

总结

通过泛型节点 GenericNode<T>,责任链模式在工作流引擎中实现了请求的动态处理。客户端通过 JSON 配置定义处理链,节点根据条件处理请求或传递给下一个节点。泛型确保了类型安全,责任链模式提供了解耦性和灵活性,适合处理多级审批或验证的工作流场景。

相关推荐
_AaronWong21 小时前
Electron 实现仿豆包划词取词功能:从 AI 生成到落地踩坑记
前端·javascript·vue.js
cxxcode21 小时前
I/O 多路复用:从浏览器到 Linux 内核
前端
用户54330814419421 小时前
AI 时代,前端逆向的门槛已经低到离谱 — 以 Upwork 为例
前端
JarvanMo21 小时前
Flutter 版本的 material_ui 已经上架 pub.dev 啦!快来抢先体验吧。
前端
雨中飘荡的记忆1 天前
OpenClaw:开源AI助手平台的革命之路
后端
恋猫de小郭1 天前
AI 可以让 WIFI 实现监控室内人体位置和姿态,无需摄像头?
前端·人工智能·ai编程
哀木1 天前
给自己整一个 claude code,解锁编程新姿势
前端
程序员鱼皮1 天前
GitHub 关注突破 2w,我总结了 10 个涨星涨粉技巧!
前端·后端·github
UrbanJazzerati1 天前
Vue3 父子组件通信完全指南
前端·面试
用户298698530141 天前
程序员效率工具:Spire.Doc如何助你一键搞定Word表格排版
后端·c#·.net