设计模式-责任链模式
创始人
2025-05-29 03:41:30

责任链模式属于行为模式

Gof定义

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

责任链模式关键点是如何将多个处理节点连成一条链。该模式使一个对象无需知道是其他哪一个对象处理其请求,仅需要知道请求处理的结果。

GOF结构

处理者handler处理它所负责的请求,如果可处理则处理,否则将该请求转发给它的后继者

模式特点

稳定点 多个节点的链式处理流程。

变化点 节点的处理的条件或者处理顺序。

扩展点 动态增删处理节点、调整处理顺序

适用点 一个请求被多个对象处理,并且集合对象应被动态指定。

应用:nginx-处理http流程的11个状态。

场景分析

员工请假流程

1 先向部门主管申请,主管进行处理。

2 部门主管无权限处理时再向他的上级申请比如项目主管,项目主管进行处理。

3 项目主管无权限处理时再向他的上级申请比如区域主管,区域主管进行处理。

4 ...申请依次向下传递,像链条一样,直到有管理者有权限处理为止。

代码实现

leave.cpp

引入模式后实现

leave_ex.cpp

测试

结论:

1 将请假流程作为一个链表,每个处理者作为处理节点。

2 从单节点出发,实现处理功能以及链表关系,完成传递功能。

3 从实现上看引入模式后代码量增大不少,但是设定了一个稳定点,后续不管是修改每个处理的条件、处理的顺序、以及增删处理都会比较简单,也更加符合设计原则。而原始代码修改这些需要不停的调整以及增删if else判断。

代码示例

leave.cpp

#include 
struct Context{int day;
};class LeaveApply{
public:bool Apply(const Context& ctx){if(!DepartmentManagerProcess(ctx)){if(!ProjectManagerProcess(ctx)){if(!RegionalManagerProcess(ctx)){return false;}}}return true;}private:bool DepartmentManagerProcess(const Context& ctx){if(ctx.day < 3){std::cout << "DepartmentManager agree" << std::endl;  return true;}return false;}bool ProjectManagerProcess(const Context& ctx){if(ctx.day < 10){std::cout << "ProjectManager agree" << std::endl;   return true;}return false;}bool RegionalManagerProcess(const Context& ctx){if(ctx.day < 30){std::cout << "RegionalManager agree" << std::endl;   return true;}return false;}
};int main(int arc,char** arg){std::cout << "leave--" << std::endl;Context ctx;ctx.day = 15;if(arc == 2){ctx.day = std::stoi(arg[1]);}LeaveApply la;if(la.Apply(ctx)){std::cout <<  ctx.day << " days off success" << std::endl;}else{std::cout <<  ctx.day << " days off failed" << std::endl;}return 0;
}

leave_ex.cpp


#include 
struct Context{int day;
};class Manager{
public:virtual bool Process(const Context& ctx) = 0;Manager* get_next(){return next_;}void set_next(Manager* manager){next_ = manager;}private:Manager* next_ = nullptr;
};class DepartmentManager : public Manager{
public:    virtual bool Process(const Context& ctx){if(ctx.day < 3){std::cout << "DepartmentManager agree" << std::endl; return true;}return false;}
};class ProjectManager : public Manager{
public:    virtual bool Process(const Context& ctx){if(ctx.day < 10){std::cout << "ProjectManager agree" << std::endl;return true;}return false;}
};class RegionalManager : public Manager{
public:    virtual bool Process(const Context& ctx){if(ctx.day < 30){std::cout << "RegionalManager agree" << std::endl;return true;}return false;}
};class LeaveApply{
public:LeaveApply(){ManageResponsibility();}~LeaveApply(){while(manager_){auto ptr = manager_;manager_ = manager_->get_next();delete ptr;ptr = nullptr;}}bool Apply(const Context& ctx){if(!manager_){return false;}Manager* cur = manager_;while(cur){if(cur->Process(ctx)){return true; }else{cur = cur->get_next();}}return false;}private:void ManageResponsibility(){Manager* dm = new DepartmentManager();Manager* pm = new ProjectManager();Manager* rm = new RegionalManager();dm->set_next(pm);pm->set_next(rm);manager_ = dm;}Manager* manager_ = nullptr;
};int main(int arc,char** arg){std::cout << "leave2--" << std::endl;Context ctx;ctx.day = 15;if(arc == 2){ctx.day = std::stoi(arg[1]);}LeaveApply la;if(la.Apply(ctx)){std::cout <<  ctx.day << " days off success" << std::endl;}else{std::cout <<  ctx.day << " days off failed" << std::endl;}return 0;
};

相关内容

热门资讯

十大券商看后市|A股风险偏好或... 临近年底,A股行情将如何演绎呢?澎湃新闻搜集了10家券商的观点,大部分券商认为,随着A股面临的海外环...
TikTok在美国支棱起来了?... 出品|虎嗅商业消费组作者|周月明编辑|苗正卿题图|视觉中国2025年12月18日,TikTok CE...
券商业绩说明会回应市场热点,资... 11月13日消息,作为上市券商与投资者之间沟通的重要纽带,业绩说明会不仅为投资者提供了一个平台,能够...