责任链模式

责任链模式(Chain of Responsibility Pattern)

定义

  • 责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下一个处理者。

核心思想

  • 解耦发送者和接收者:发送者不需要知道具体由哪个对象处理请求

  • 动态构建处理链:可以灵活地调整或扩展处理流程

  • 多处理机会:请求可以被链中的多个对象处理,也可以不被处理

模式结构

Handler(抽象处理者)
│
├── ConcreteHandlerA(具体处理者A)
├── ConcreteHandlerB(具体处理者B)
└── ConcreteHandlerC(具体处理者C)

关键组件:

  • Handler:定义处理请求的接口,通常包含设置后继者的方法

  • ConcreteHandler:具体处理者,处理其负责的请求,否则将请求转发给后继者

  • Client:向链上的具体处理者对象提交请求

主要解决的问题

  • 请求发送者与接收者耦合:避免请求发送者与特定接收者绑定

  • 动态指定请求处理者:运行时可以动态改变处理请求的对象

  • 多级处理需求:当需要多个对象都有机会处理请求时

代码示例

  • 场景描述
    实现一个采购审批系统,不同级别的管理者有不同的审批权限:
    经理:可审批金额 ≤ 5000
    总监:可审批金额 ≤ 10000
    CEO:可审批金额 ≤ 50000
using System;

// 采购请求
public class PurchaseRequest
{
    public decimal Amount { get; set; }
    public string Purpose { get; set; }
    
    public PurchaseRequest(decimal amount, string purpose)
    {
        Amount = amount;
        Purpose = purpose;
    }
}

// 抽象处理者
public abstract class Approver
{
    protected Approver Successor { get; private set; }
    protected string Name { get; }
    
    protected Approver(string name)
    {
        Name = name;
    }
    
    public void SetSuccessor(Approver successor)
    {
        this.Successor = successor;
    }
    
    public abstract void ProcessRequest(PurchaseRequest request);
}

// 具体处理者 - 经理
public class Manager : Approver
{
    public Manager(string name) : base(name) {}
    
    public override void ProcessRequest(PurchaseRequest request)
    {
        if (request.Amount <= 5000)
        {
            Console.WriteLine($"经理 {Name} 审批了采购请求:金额 {request.Amount},用途 {request.Purpose}");
        }
        else if (Successor != null)
        {
            Successor.ProcessRequest(request);
        }
    }
}

// 具体处理者 - 总监
public class Director : Approver
{
    public Director(string name) : base(name) {}
    
    public override void ProcessRequest(PurchaseRequest request)
    {
        if (request.Amount <= 10000)
        {
            Console.WriteLine($"总监 {Name} 审批了采购请求:金额 {request.Amount},用途 {request.Purpose}");
        }
        else if (Successor != null)
        {
            Successor.ProcessRequest(request);
        }
    }
}

// 具体处理者 - CEO
public class CEO : Approver
{
    public CEO(string name) : base(name) {}
    
    public override void ProcessRequest(PurchaseRequest request)
    {
        if (request.Amount <= 50000)
        {
            Console.WriteLine($"CEO {Name} 审批了采购请求:金额 {request.Amount},用途 {request.Purpose}");
        }
        else
        {
            Console.WriteLine($"金额过大({request.Amount}),需要董事会讨论!");
        }
    }
}

// 客户端代码
class Program
{
    static void Main(string[] args)
    {
        // 创建处理者
        var manager = new Manager("张经理");
        var director = new Director("李总监");
        var ceo = new CEO("王CEO");
        
        // 构建责任链
        manager.SetSuccessor(director);
        director.SetSuccessor(ceo);
        
        // 创建不同金额的采购请求
        var requests = new[]
        {
            new PurchaseRequest(4000, "购买办公用品"),
            new PurchaseRequest(8000, "团队建设活动"),
            new PurchaseRequest(30000, "新服务器采购"),
            new PurchaseRequest(100000, "新建办公楼")
        };
        
        // 处理请求
        foreach (var request in requests)
        {
            manager.ProcessRequest(request);
        }
        
        /* 输出:
        经理 张经理 审批了采购请求:金额 4000,用途 购买办公用品
        总监 李总监 审批了采购请求:金额 8000,用途 团队建设活动
        CEO 王CEO 审批了采购请求:金额 30000,用途 新服务器采购
        金额过大(100000),需要董事会讨论!
        */
    }
}

总结

优点

  • 降低耦合度:请求发送者无需知道具体处理者

  • 增强灵活性:可以动态地重新组织链或新增处理者

  • 明确责任划分:每个处理者只需关注自己责任范围内的请求

  • 符合开闭原则:新增处理者无需修改现有代码

缺点

  • 请求可能未被处理:没有明确的接收者保证

  • 性能影响:较长的责任链可能影响性能

  • 调试困难:请求的传递过程可能比较复杂

适用场景

  • 有多个对象可以处理同一个请求,但具体由哪个对象处理在运行时自动确定

  • 想在不明确指定接收者的情况下向多个对象中的一个提交请求

  • 需要动态指定一组对象处理请求

责任链模式在审批流程、异常处理、事件处理等场景中非常有用。

posted @ 2025-04-14 15:02  刘继先  阅读(21)  评论(0)    收藏  举报