设计模式---数据结构模式之职责链模式(Chain of Responsibility)
一:概念
职责链模式(CoR,Chain of Responsibility)是行为模式之一,该模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的对象之间像链条一样紧密相连,所以被称作职责链模式。
例1:比如客户Client要完成一个任务,这个任务包括a,b,c,d四个部分。
首先客户Client把任务交给A,A完成a部分之后,把任务交给B,B完成b部分,…,直到D完成d部分。
例2:比如政府部分的某项工作,县政府先完成自己能处理的部分,不能处理的部分交给省政府,省政府再完成自己职责范围内的部分,不能处理的部分交给中央政府,中央政府最后完成该项工作。
例3:软件窗口的消息传播。
例4:SERVLET容器的过滤器(Filter)框架实现。
二:动机
在软件构建的过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少的带来请求发送者与接受者的耦合。
如何使请求的发送者不需要指定具体的接受者?让请求的接受者自己在运行时决定来处理请求,从而使两者解耦。
三:模式定义
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链(链表),并沿着这条链传递请求,直到有一个对象处理它为止。
——《设计模式》GoF
四:代码讲解
(一)Request对象:携带请求信息
class Reqest { string description; RequestType reqType; public: Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {} RequestType getReqType() const { return reqType; } const string& getDescription() const { return description; } };
(二)ChainHandler基类处理者:
class ChainHandler{ ChainHandler *nextChain; //多态指针指向自己,形成了多态链表
void sendReqestToNextHandler(const Reqest & req) //若是我的链表的下一个结点不为空,那么久传递给下一个结点进行处理 { if (nextChain != nullptr) nextChain->handle(req); } protected: virtual bool canHandleRequest(const Reqest & req) = 0; //判断请求能否处理,运行时判断 virtual void processRequest(const Reqest & req) = 0; //具体处理业务逻辑 public: ChainHandler() { nextChain = nullptr; } void setNextChain(ChainHandler *next) { nextChain = next; } //建立链表 void handle(const Reqest & req) //调用方法处理逻辑,当前无法处理,使用下一个 { if (canHandleRequest(req)) processRequest(req); else sendReqestToNextHandler(req); } };
(三)Handler具体处理对象
class Handler1 : public ChainHandler{ protected: bool canHandleRequest(const Reqest & req) override { return req.getReqType() == RequestType::REQ_HANDLER1; } void processRequest(const Reqest & req) override { cout << "Handler1 is handle reqest: " << req.getDescription() << endl; } }; class Handler2 : public ChainHandler{ protected: bool canHandleRequest(const Reqest & req) override { return req.getReqType() == RequestType::REQ_HANDLER2; } void processRequest(const Reqest & req) override { cout << "Handler2 is handle reqest: " << req.getDescription() << endl; } }; class Handler3 : public ChainHandler{ protected: bool canHandleRequest(const Reqest & req) override { return req.getReqType() == RequestType::REQ_HANDLER3; } void processRequest(const Reqest & req) override { cout << "Handler3 is handle reqest: " << req.getDescription() << endl; } };
(四)构建链表
int main(){ Handler1 h1; Handler2 h2; Handler3 h3; h1.setNextChain(&h2); //构建链表 h2.setNextChain(&h3); Reqest req("process task ... ", RequestType::REQ_HANDLER3); //获取请求,设置类型 h1.handle(req); //处理请求 return 0; }
五:类图(结构)
职责链模式在现在C++中使用不多。但是这种思想还是值得借鉴,比如在python中Django框架数据添加扩展中提到的也是这样的,只要前面不抛出异常,就接着执行
六:要点总结
(一)Chain of Responsibility模式的应用场合在于“一个请求可能有多个接受者,但是最后真正接受者只有一个”,这时候请求发送者与接受者的耦合可能出现“变化脆弱”的症状,职责链的目的就是将二者解耦,从而更好的应对变化。
(二)应用了Chain of Responsibility模式后,对象的职责分派将更具灵活性。我们可以在运行时动态添加/修改请求的处理指责。
(三)如果请求传递到职责链的末尾仍得不到处理,应该有一个合理的缺省机制。这也是每一个接受者对象的责任,而不是发出请求的对象的责任。
七:案例实现(代码样例)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <string> using namespace std; enum class RequestType { REQ_HANDLER1, REQ_HANDLER2, REQ_HANDLER3 }; class Reqest { string description; RequestType reqType; public: Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {} RequestType getReqType() const { return reqType; } const string& getDescription() const { return description; } }; class ChainHandler{ ChainHandler *nextChain; void sendReqestToNextHandler(const Reqest & req) { if (nextChain != nullptr) nextChain->handle(req); } protected: virtual bool canHandleRequest(const Reqest & req) = 0; virtual void processRequest(const Reqest & req) = 0; public: ChainHandler() { nextChain = nullptr; } void setNextChain(ChainHandler *next) { nextChain = next; } void handle(const Reqest & req) { if (canHandleRequest(req)) processRequest(req); else sendReqestToNextHandler(req); } }; class Handler1 : public ChainHandler{ protected: bool canHandleRequest(const Reqest & req) override { return req.getReqType() == RequestType::REQ_HANDLER1; } void processRequest(const Reqest & req) override { cout << "Handler1 is handle reqest: " << req.getDescription() << endl; } }; class Handler2 : public ChainHandler{ protected: bool canHandleRequest(const Reqest & req) override { return req.getReqType() == RequestType::REQ_HANDLER2; } void processRequest(const Reqest & req) override { cout << "Handler2 is handle reqest: " << req.getDescription() << endl; } }; class Handler3 : public ChainHandler{ protected: bool canHandleRequest(const Reqest & req) override { return req.getReqType() == RequestType::REQ_HANDLER3; } void processRequest(const Reqest & req) override { cout << "Handler3 is handle reqest: " << req.getDescription() << endl; } }; int main(){ Handler1 h1; Handler2 h2; Handler3 h3; h1.setNextChain(&h2); h2.setNextChain(&h3); Reqest req("process task ... ", RequestType::REQ_HANDLER3); h1.handle(req); system("pause"); return 0; }
八:案例实现(处理汽车)
(一)handle基类实现
class CarHandler { protected: CarHandler* nextHandler; public: virtual void HandlerCar() = 0; public: CarHandler* SetNextHandler(CarHandler* hand) { this->nextHandler = hand; return this->nextHandler; } virtual ~CarHandler(){} };
(二)实现具体处理子类
class CarHandleHead :public CarHandler { public: virtual void HandlerCar() { cout << "composite car head" << endl; if (nextHandler != NULL) nextHandler->HandlerCar(); } }; class CarHandleBody :public CarHandler { public: virtual void HandlerCar() { cout << "composite car body" << endl; if (nextHandler != NULL) nextHandler->HandlerCar(); } }; class CarHandleTail :public CarHandler { public: virtual void HandlerCar() { cout << "composite car tail" << endl; if (nextHandler != NULL) nextHandler->HandlerCar(); } };
(三)组合责任链,开始演示
void main() { CarHandler* CH = new CarHandleHead(); CarHandler* CB = new CarHandleBody(); CarHandler* CT = new CarHandleTail(); CH->SetNextHandler(CB); CB->SetNextHandler(CT); CH->HandlerCar(); delete CH; delete CB; delete CT; system("pause"); return; }
作者:山上有风景
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!