Chain of Responsibility:责任链模式

本文介绍了一种设计模式——责任链模式。此模式通过定义一系列处理者,并为它们建立起等级关系来处理请求。当一个请求被提交后,它会被传递给最低级别的处理者,之后逐级向上直至找到能够处理它的处理者。

      现有多个处理者。这些处理者可以处理不同的请求。这些处理者有等级关系,每个处理者都有更上级的处理者。对于最上级的处理者,可以没有上级。对于一个上级处理者,可以有多个下级处理者。

客户端发出了一个请求,请求被传递给一个最下级处理者。而该处理者无法处理该请求,于是将该请求发送给自己的上级。上级的处理者无法处理该请求,于是将该请求再度发往自己的上级……直到有某个处理者可以处理该请求。如果请求发送给最上级依然无法被处理,那么该请求就需要被抛出异常,或者有其他处理方式。

这一级一级的关系就像链条,故称之为责任链模式。

 

1.    定义请求

请求的定义是公开的,即必须为所有人可见,无论是客户还是处理者。

enum eRequest
{
	requestLevelA,
	requestLevelB,
	requestLevelC,
};
// 请求
class Request
{
public:
	eRequest _request;
};

2.    定义处理者基类

处理者基类规定了处理者的接口。

同时每个处理者存有上级的指针,当自身无法处理某个请求时,将该请求提交给自己的上级。

// 处理者
class Manager
{
public:
	//设置直接上级
	void setSuperior(Manager* superior) { _superior = superior; }
	//要求处理请求
	virtual void askForRequest(Request* request) = 0;
protected:
	Manager* _superior;
};

3.    定义处理者派生类

处理者派生类在请求处理函数中会对请求进行分析。若请求自身可以进行处理,那么处理;否则提交给自己的上级。

// 团队队长
class TeamLeader : public Manager
{
public:
	virtual void askForRequest(Request* request)
	{
		if (request->_request == requestLevelA)
		{
			处理请求
		}
		else
		{
			_superior->askForRequest(request);
		}
	};
};

// 总监
class Majordomo : public Manager
{
public:
	virtual void askForRequest(Request* request)
	{
		if (request->_request == requestLevelB)
		{
			处理请求
		}
		else
		{
			_superior->askForRequest(request);
		}
	};
};

// 老板
class Boss : public Manager
{
public:
	// 老板可以处理所有请求
	virtual void askForRequest(Request* request)
	{
		处理请求
	}
};

4.    用户使用

用户产生一个请求,然后将该请求提交给最低级的处理者即可。无论用户产生什么样的请求,都是如此。

void main()
{
	Manager* leader = new TeamLeader();
	Manager* major = new Majordomo();
	Boss* boss = new Boss();
	leader->setSuperior(major);
	major->setSuperior(boss);

	Request* rq = new Request();

	rq->_request = requestLevelA;
	leader->askForRequest(rq);

	rq->_request = requestLevelB;
	leader->askForRequest(rq);

	rq->_request = requestLevelC;
	leader->askForRequest(rq);
}
 

    责任链模式,一定要注意请求的配置,务必确保每一个请求都有某个级别的处理者可以进行处理。否则,当责任链走完,很可能请求没有被处理,那么就只能抛出异常,或使用通用的请求处理。

    一个责任链,可以是一条线,一棵树,或者一个环。对于环形的责任链,不存在最上级。这种情况下,请求必须可以被某个处理者处理,否则会死循环。

    下图是一个树形的责任链:

<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]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值