🔍 一、职责链模式是什么?

职责链模式 是一种行为型设计模式,用于将请求的处理者组成一条链,并沿着这条链传递请求,直到有一个处理者处理它为止。

核心思想: 让多个对象都有机会处理请求,但每个对象只负责一部分,谁能处理就谁处理,不能处理就传给下一个。


🧠 二、通俗理解

假设你请假:

  • 先找 组长 批准(请假 1 天以内)

  • 超过 1 天,组长说:“我批不了,你去找经理”

  • 超过 3 天,经理说:“我批不了,你找总监”

这就是典型的职责链模式——请求从链首传起,层层传递,直到被处理。


🧱 三、UML 类图结构

+----------------------+
|     Handler (抽象类)  |
|----------------------|
| - next: Handler       |
| + SetNext(Handler)    |
| + Handle(request)     |
+----------------------+
            ▲
            |
+-----------------------+    +-----------------------+
| ConcreteHandlerA      |    | ConcreteHandlerB      |
|-----------------------|    |-----------------------|
| + Handle(request)     |    | + Handle(request)     |
+-----------------------+    +-----------------------+

🧩 四、代码示例

第一种是实现方式 : 用链表方式(骨架代码非实例)




namespace DesignPatternsPractice.Src.Behavioral.ChainOfResponsibility
{
    /// <summary>
    /// 实践 职责链模式 代码骨架(极客时间)
    /// </summary>
    public class ChainOfResponsibility2
    {
        // main()
    }

    public abstract class Handle
    {
        protected Handle successor = null; // 指向下一个处理者的引用

        public void setSuccessor(Handle successor)
        {
            this.successor = successor;
        }

        public void handle()
        {
            bool handle = doHandle(); // 当前处理者尝试处理
            if (successor != null && !handle) // 如果未处理且有下一个处理者
            {
                successor.handle(); // 传递给下一个处理者
            }
        }

        protected abstract bool doHandle(); // 具体处理逻辑由子类实现
    }

    public class HandleA : Handle
    {
        protected override bool doHandle()
        {
            bool handled = false;
            // 实际处理逻辑
            return handled;
        }
    }

    public class HandleB : Handle
    {
        protected override bool doHandle()
        {
            bool handled = false;
            // 实际处理逻辑
            return handled;
        }
    }

    public class HandleChain
    {
        private Handle _head; // 链的头部
        private Handle _tail; // 链的尾部

        public void addHandler(Handle handle)
        {
            handle.setSuccessor(null); // 确保新处理者没有后续节点

            if (_head == null) // 如果链是空的
            {
                _head = handle; // 新处理者既是头
                _tail = handle; // 也是尾
                return;
            }
            
            _tail.setSuccessor(handle); // 当前尾部指向新处理者  *(这里要是不set的话插入第三个的时候,第二个和第三个之间的指向就无了)
            _tail = handle; // 更新尾部为新处理者
        }
        public void handle()
        {
            if (_head != null)
            {
                _head.handle(); // 从头部开始处理
            }
        }
    }
}

使用第二种方式实现:列表遍历(简单)

这个实例用第二种方式实现了一个发消息敏感词屏蔽功能

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace DesignPatternsPractice.Src.Behavioral.ChainOfResponsibility
{
    /// <summary>
    /// 职责链模式 (实例)
    /// 职责链模式来过滤敏感词。 
    ///     这种需求就需要每个职责链都要处理
    /// </summary>
    public class ChainOfResponsibilityExample
    {
        static void Main()
        {
            SensitiveWordFilterChain senChain = new SensitiveWordFilterChain();
            senChain.addFilter(new SexyWordFilter());
            senChain.addFilter(new ViolentWordFilter());

            while (true)
            {
                Console.WriteLine("请输入呀发送的消息:(你最好文明用语)");
                string? v = Console.ReadLine();
                
                if (string.IsNullOrEmpty(v))
                {
                    Console.WriteLine("不输入你让我怎么过滤?回答我!!!!\n");
                }
                else
                {
                    bool v1 = senChain.Filter(new Content(v));
                    if (v1)
                        Console.WriteLine($"您输入的消息为“{senChain.content.message}”,系统审核可以发送\n");
                    else
                        Console.WriteLine($"您输入的消息含有暴力词汇,所以你丫最好是好好说话!\n");


                }
            }
        }
    }

    public class Content
    {
        public string message { set; get; }

        public Content(string message)
        {
            this.message = message;
        }
    }
    public interface SensitiveWordFailter
    {
        bool doFilter(Content content);
    }

    /// <summary>
    /// 涉及色情的 打上*
    /// </summary>
    public class SexyWordFilter : SensitiveWordFailter
    {

        public bool doFilter(Content content)
        {

            string message = content.message;
            string v = message.Replace("逼", "*").Replace("操", "*");
            content.message = v;
            return true;
        }
    }
    /// <summary>
    /// 暴力词汇
    /// </summary>
    public class ViolentWordFilter : SensitiveWordFailter
    {
        string[] keyWords = { "死", "杀", "枪" };
        public bool doFilter(Content content)
        {
           
            if (keyWords.Any(content.message.Contains))
                return false;
            return true;
        }
    }

    public class SensitiveWordFilterChain
    {
        private List<SensitiveWordFailter> sensitiveWordFailters = new List<SensitiveWordFailter>();

        public Content content { set; get; }

        public void addFilter(SensitiveWordFailter sensitiveWordFailter)
        {
            sensitiveWordFailters.Add(sensitiveWordFailter);
        }

        public bool Filter(Content content)
        {
            foreach (SensitiveWordFailter item in sensitiveWordFailters)
            {
                if (!item.doFilter(content))
                {
                    return false;
                }
            }
            this.content = content;
            return true;
        }
    }


}

❗需要注意的是:

在职责链种处理职责的时候 可以处理后直接返回,也可也全部处理,需按实际需求修改代码!比如上面的第二种例子就是将全部职责都处理


💡 五、适用场景

职责链适用于以下情况:

  • 有多个对象可以处理同一个请求;

  • 不明确处理请求的具体对象是谁;

  • 需要动态组合责任链条,便于扩展处理逻辑;

  • 需要解耦请求发送者和处理者


✅ 六、优点

优点

描述

✔️ 解耦

发送者与接收者解耦,方便新增/移除处理者

✔️ 灵活

可以动态调整链的结构,顺序自由

✔️ 单一职责

每个处理者只处理自己负责的部分


❌ 七、缺点

缺点

描述

❗ 不易调试

请求可能传很远才能处理,调试复杂

❗ 性能风险

如果链太长或一直没人处理,可能导致性能问题或请求丢失

❗ 不透明性

调用者不知道最终由谁处理了请求


📦 八、常见应用场景

场景

描述

UI 事件处理

鼠标点击事件冒泡传递(如 Unity/Android)

审批流程系统

多级审批、权限分发

日志记录系统

不同等级日志(Debug → Info → Error)

中间件处理链

如 ASP.NET Core 的 Middleware 管道

游戏技能判定

一个攻击触发多个buff/debuff逻辑判断


🆚 九、与策略模式的区别

特点

策略模式

职责链模式

目标

选择一种算法

多个处理器链式尝试

客户端选择

客户端指定策略

客户端只发请求,处理器链自行处理

控制流

一次调用

多次尝试,直到被处理


✅ 十、总结

要点

描述

本质

将请求的处理职责按链条传递

优点

解耦发送者和接收者,便于扩展

使用

处理流程灵活、动态组合处理节点

成本

调试复杂,链条设计需谨慎


如果你正在做游戏技能效果解析,比如触发技能后:

  • 先判断是否暴击(处理器1)

  • 判断目标是否有护盾(处理器2)

  • 应用减速效果(处理器3)…

就非常适合用职责链模式来解耦和组织逻辑。是否需要我帮你设计一个游戏场景下的职责链模式代码示例?