13 责任链(Chain of Responsibility)模式

责任链模式

1.1 分类

(对象)行为型

1.2 提出问题

开发一款故障报修系统,不同的业务员处理的故障不同,如何确保客户的维修请求得到妥善的处理。

1.3 解决方案

使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

1.4 实现类图

在这里插入图片描述

  1. 处理者(Handler)声明了所有具体处理者的通用接口。
  2. 基础处理者(Base Handler)是一个可选的类,你可以将所有处理者共用的样本代码放置在其中。
  3. 具体处理者(Concrete Handlers)包含处理请求的实际代码。 每个处理者接收到请求后,都必须决定是否进行处理,以及是否沿着链传递请求。
  4. 客户端(Client)可根据程序逻辑一次性或者动态地生成链请求可发送给链上的任意一个处理者。

1.5 示例代码

#include <iostream>
#include <string>
#include <list>

//class Handler {
//public:
//    virtual Handler* setNext(Handler* handler) = 0;
//    virtual std::string handle(std::string request) = 0;
//};

class BaseHandler/*:public Handler*/{
private:
    BaseHandler* m_nextHandler;
public:
    BaseHandler* setNext(BaseHandler* handler) {
        m_nextHandler = handler;
        return m_nextHandler;
    }
    virtual std::string handle(std::string request) {
        if (m_nextHandler) {
            return m_nextHandler->handle(request);
        }
        return "";
    }
};

class RobotAI : public BaseHandler {
public:
    std::string handle(std::string request) override {
        if (request == "使用向导") {
            return "RobotAI:我来处理-" + request + "-。\n";
        } else {
            return BaseHandler::handle(request);
        }
    }
};
class TelOperator : public BaseHandler {
public:
    std::string handle(std::string request) override {
        if (request == "常见问题") {
            return "TelOperator:我来处理-" + request + "-。\n";
        } else {
            return BaseHandler::handle(request);
        }
    }
};
class Expert : public BaseHandler {
public:
    std::string handle(std::string request) override {
        if (request == "疑难杂症") {
            return "Expert:我来处理-" + request + "-。\n";
        } else {
            return BaseHandler::handle(request);
        }
    }
};

void clientCode(BaseHandler& handler) {
    std::list<std::string> problems = { "疑难杂症","常见问题","使用向导","常见问题","扯淡的问题" };
    for (const std::string& problem : problems) {
        std::string result = handler.handle(problem);
        std::cout << "Client:谁来处理" << problem<<":\n";
        if (result.empty()) {
            std::cout << "处理结果:" << "没人能够处理。\n";
        } else {
            std::cout << "处理结果:" << result;
        }
    }
}
int main()
{
    RobotAI robot;
    TelOperator telOperator;
    Expert expert;
    robot.setNext(&telOperator)->setNext(&expert);
    std::cout << "Chain:机器人AI->话务员->专家\n";
    clientCode(robot);

    //clientCode(telOperator);
}

1.6 举个栗子

责任链模式负责为活动的 GUI 元素显示上下文帮助信息。
在这里插入图片描述

1.7 总结

1.7.1 优点

  1. 你可以控制请求处理的顺序。
  2. 单一职责原则。你可对发起操作和执行操作的类进行解耦。
  3. 开闭原则。你可以在不更改现有代码的情况下在程序中新增处理者。

1.7.2 缺点

部分请求可能未被处理。

<think>我们正在讨论责任链模式Chain of Responsibility)。根据引用[1],责任链模式是一种行为设计模式,它通过将请求沿着处理者链传递来避免请求发送者和接收者之间的耦合。多个处理者对象都有机会处理请求,直到其中一个处理它为止。 引用[2]提供了一段示例代码,展示了责任链模式的实现方式。代码中定义了一个处理者基类CHandler,它包含一个指向下一个处理者的指针(m_pHandler)和一个处理请求的虚函数HandleRequest。然后定义了三个具体的处理者类(CConcreteHandler1, CConcreteHandler2, CConcreteHandler3),每个具体处理者根据自己的条件决定是否处理请求,如果不处理则传递给下一个处理者。 因此,我们可以这样介绍责任链模式责任链模式Chain of Responsibility)是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理它为止。这种模式解耦了请求的发送者和接收者,允许多个对象都有机会处理请求。 责任链模式的主要组成部分: 1. 处理者(Handler):定义一个处理请求的接口,通常包含一个指向下一个处理者的引用(后继者链接)。在示例代码中,CHandler就是抽象处理者。 2. 具体处理者(Concrete Handler):实现处理请求的具体逻辑。如果自己能够处理请求,则处理;否则将请求传递给后继者。示例代码中的CConcreteHandler1、CConcreteHandler2、CConcreteHandler3就是具体处理者。 责任链模式的特点: - 降低了对象之间的耦合度:请求发送者无需知道哪个对象会处理其请求。 - 增强了系统的可扩展性:可以动态地增加或修改处理者链。 - 增强了给对象指派职责的灵活性:通过改变链内的成员或者调整次序,可以动态地改变处理流程。 - 责任链简化了对象之间的连接:每个处理者只需保持一个指向其后继者的引用,而不需保持所有处理者的引用。 - 责任分担:每个处理者只需处理自己能够处理的请求,将不能处理的请求传递给下一个处理者,符合类的单一职责原则。 但是,责任链模式也有缺点: - 不能保证请求一定被处理:如果链中没有合适的处理者,请求可能到达链的末端也没有被处理。 - 对于较长的责任链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。 - 调试时可能比较复杂,特别是链条较长时,逻辑可能不易追踪。 应用场景: 责任链模式适用于以下情况: - 有多个对象可以处理同一个请求,具体哪个对象处理该请求在运行时自动确定。 - 需要动态指定一组对象处理请求,或者需要动态添加、删除处理者。 - 在不明确指定接收者的情况下,向多个对象中的一个提交请求。 下面我们用一段标准化的代码示例(使用C++)来展示责任链模式: ```cpp #include <iostream> // 抽象处理者 class Handler { public: virtual ~Handler() {} void SetNext(Handler* next) { next_ = next; } virtual void HandleRequest(int request) const = 0; protected: Handler* next_ = nullptr; }; // 具体处理者A class ConcreteHandlerA : public Handler { public: void HandleRequest(int request) const override { if (request < 10) { std::cout << "ConcreteHandlerA handled request " << request << "\n"; } else if (next_ != nullptr) { next_->HandleRequest(request); } } }; // 具体处理者B class ConcreteHandlerB : public Handler { public: void HandleRequest(int request) const override { if (request >= 10 && request < 20) { std::cout << "ConcreteHandlerB handled request " << request << "\n"; } else if (next_ != nullptr) { next_->HandleRequest(request); } } }; // 具体处理者C class ConcreteHandlerC : public Handler { public: void HandleRequest(int request) const override { if (request >= 20) { std::cout << "ConcreteHandlerC handled request " << request << "\n"; } else if (next_ != nullptr) { next_->HandleRequest(request); } } }; // 客户端代码 int main() { ConcreteHandlerA handlerA; ConcreteHandlerB handlerB; ConcreteHandlerC handlerC; handlerA.SetNext(&handlerB); handlerB.SetNext(&handlerC); // 创建一系列请求 int requests[] = {5, 15, 25}; for (int req : requests) { handlerA.HandleRequest(req); } return 0; } ``` 在这个示例中,我们创建了三个具体处理者(ConcreteHandlerA、ConcreteHandlerB、ConcreteHandlerC),它们分别处理不同范围的请求。客户端将请求发送给链中的第一个处理者(handlerA),然后请求沿着链传递直到被处理。 责任链模式在现实中的应用包括: - 事件处理系统(如GUI中的事件冒泡) - 日志记录器(不同级别的日志由不同的记录器处理) - Web框架中的中间件(每个中间件可以处理请求并决定是否传递给下一个) - 异常处理(try-catch块可以看作是一个责任链) 相关问题: 1. 责任链模式在哪些实际框架或库中有应用? 2. 如何处理责任链中请求未被处理的情况? 3. 责任链模式和状态模式有什么区别? 4. 如何动态地修改责任链的结构? </think>### 责任链模式Chain of Responsibility)介绍 责任链模式Chain of Responsibility)是一种**行为型设计模式**,核心思想是将多个处理对象连接成一条链,请求沿链传递直至被处理。这种模式解耦了请求发送者和接收者,允许多个对象都有机会处理请求。以下是详细解析: --- #### 一、核心结构与原理 1. **处理者(Handler)抽象类** 定义处理请求的接口,包含: - 指向下一个处理者的引用(`m_pHandler`) - 处理请求的虚方法(`HandleRequest()`) ```cpp class Handler { public: void SetNext(Handler* next) { m_pNext = next; } virtual void HandleRequest(int request) = 0; protected: Handler* m_pNext = nullptr; // 后继处理者 }; ``` 2. **具体处理者(Concrete Handler)** 实现具体的处理逻辑,若无法处理则转发给下一个处理者: ```cpp class ConcreteHandlerA : public Handler { public: void HandleRequest(int request) override { if (request < 10) std::cout << "HandlerA processed request: " << request << "\n"; else if (m_pNext) m_pNext->HandleRequest(request); // 传递给下一个 } }; ``` 3. **客户端调用** 构建处理链并发送请求: ```cpp int main() { Handler* handlerA = new ConcreteHandlerA(); Handler* handlerB = new ConcreteHandlerB(); handlerA->SetNext(handlerB); // 设置责任链 handlerA->HandleRequest(15); // 请求在链上传递 } ``` --- #### 二、关键特性 1. **解耦性** 请求发送者无需知道具体处理者,只需向链首提交请求[^1]。 2. **动态扩展** 可随时增减或调整处理者节点(如添加 `ConcreteHandlerC`)。 3. **处理灵活性** 请求可能被链中任意节点处理,也可能未被任何节点处理。 4. **符合开闭原则** 新增处理者无需修改现有代码。 --- #### 三、适用场景 1. **多级请求处理** 如审批流程(员工→经理→CEO)、日志级别过滤(DEBUG→INFO→ERROR)。 2. **动态指定处理对象** 例如中间件管道(如Express.js的中间件链)。 3. **未知接收者的场景** 如GUI事件冒泡机制(控件→父容器→窗口)。 --- #### 四、优缺点分析 | **优点** | **缺点** | |-----------------------------------|--------------------------| | 降低耦合度(请求发送者与接收者分离) | 请求可能未被处理(链尾无兜底) | | 动态增删处理节点 | 长链可能影响性能 | | 简化对象间连接(单向链式传递) | 调试复杂度较高 | --- #### 五、与其他模式的关系 - **与装饰器模式** 两者都基于链式结构,但装饰器模式重在**增强功能**,责任链重在**分发请求**。 - **与状态模式** 状态模式通过状态转移改变行为,责任链通过固定链条传递请求。 --- ### 相关问题 1. 责任链模式如何处理请求未被任何节点处理的情况? 2. 在实际框架(如Spring、Express.js)中责任链模式有哪些典型应用? 3. 如何在责任链模式中实现请求的优先级处理? 4. 责任链模式与命令模式结合会产生什么效果? [^1]: 责任链模式通过对象链解耦请求发送者和接收者[^1]。 [^2]: 具体处理者通过条件判断决定是否处理请求[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值