设计模式 ---- 责任链模式

责任链模式

首先要明白什么是“链”。

在 C++ 中,我们经常会接触到链表。

例如一个单向链表,每个节点都会保存一个指向下一个节点的指针:

Node* next;

当前节点处理完之后,可以通过 next 找到下一个节点。

如果是双向链表,那么节点除了保存下一个节点的指针之外,还会保存一个指向上一个节点的指针:

Node* next;
Node* prev;

责任链模式中的“链”,在某种程度上和这个思想类似:

将多个处理者按照一定顺序连接起来,一个处理者处理不了,就将请求交给下一个处理者。

不过需要注意,责任链模式中的“链”并不一定真的使用 C++ 的链表实现。

这里的“链”更多的是一种对象之间的组织关系


什么是“责任”?

“责任”可以理解成:

当前对象是否有能力、也是否应该处理这个请求。

责任链上每个节点实际上都承担了一部分“责任”。

这里的“责任”并不是说:

“这个对象一定要处理这个请求。”

而是:

“这个对象有能力处理某一部分请求,如果自己无法处理,就继续向后传递。”


责任链真正的核心

这样就可以把责任链拆成两个非常重要的部分。

1. 责任

每个节点都有自己的处理范围

例如:(射击游戏)

载具:处理 普通伤害
护盾:处理 贯穿载具 100 伤害
血量:处理 超出贯穿 100 伤害的部分

每个节点只需要关心:

“这个请求是不是我的责任?”

而不需要知道整个系统应该怎么处理。


2. 链

把这些处理者连接起来:

载具 → 护甲 → 徐良

当组长拿到请求时:

请求
 ↓
载具
 ↓
能处理?
 ├─ 是 → 载具承担伤害
 └─ 否 → 护盾
          ↓
        能处理?
         ├─ 是 → 护盾免伤
         └─ 否 → 扣血

这就是责任链模式最核心的流程。


为什么不直接使用 if-else

这里其实有一个很有意思的地方:

为什么不直接写一大堆 if-else

例如我们完全可以这么写:

if (damage.type == Through)
{
    vehicles.Handle();
}
else if (damage <= 100)
{
    shield.Handle();
}
else if (damage <= 999)
{
    characterHealth.Handle();
}

功能上完全可以实现。

但是问题来了。

假如以后增加:

爆炸伤害
毒气
法术伤害

那么这个 if-else 会越来越长:

if (...)
{
}
else if (...)
{
}
else if (...)
{
}
else if (...)
{
}
else if (...)
{
}
else if (...)
{
}

而且处理规则和具体的处理者全部耦合在了一起。

责任链模式希望解决的就是这个问题:

把“谁来处理请求”的判断,从一个巨大的集中式 if-else 中拆出来,让每个处理者只负责自己的责任范围。

于是变成:

请求
 ↓
Handler A
 ↓
Handler B
 ↓
Handler C
 ↓
Handler D

每个 Handler 只需要知道:

我能处理 → 我处理

我不能处理 → 找下一个

而不需要知道:

下一个到底是谁?
整个系统一共有多少个处理者?

责任链的基本代码结构

可以先定义一个抽象的处理者:

class Handler
{
protected:
    Handler* next = nullptr;

public:
    void SetNext(Handler* handler)
    {
        next = handler;
    }

    virtual void Handle(int days) = 0;
};

然后不同的处理者承担不同的责任。

载具

class Vehicles : public Handler
{
public:
    void Handle(int damage) override
    {
        // handle code;
    }
};

护盾

class Shield : public Handler
{
public:
    void Handle(int days) override
    {
        // Shield Handle
    }
};

总监

class CharacterHealth : public Handler
{
public:
    void Handle(int days) override
    {
        // character handle;
    }
};

最后把它们连接起来:

Vehicles vehicles;
Shield shield;
CharacterHealth characterHealth;

Vehicles.SetNext(&shield);
Shield.SetNext(&characterHealth);

形成:

Vehicles
  ↓
Shield
  ↓
CharacterHealth

客户端只需要:

vehicles.Handle(Damgae damgae);

它并不需要知道:

普通伤害应该找谁?
载具处理不了找护盾?

这些都由责任链内部完成。


责任链的核心

虽然上述例子可能并不是很恰当,大概意思就是链条传递责任,外部不需要知道具体内部结构

责任链的核心浓缩成:

责任链模式的核心,就是将多个具有不同处理能力的对象连接起来,让请求沿着这条链依次传递,每个对象判断自己是否能够处理这个请求;能够处理就处理,不能处理就交给下一个对象。

责任链的重点不是“链”,而是“请求的处理者可以动态地传递责任”,从而避免客户端与具体处理者之间产生强耦合。

posted on 2026-09-11 21:40  咸云闲鱼  阅读(3)  评论(0)    收藏  举报