责任链模式属于行为模式
Gof定义
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
责任链模式关键点是如何将多个处理节点连成一条链。该模式使一个对象无需知道是其他哪一个对象处理其请求,仅需要知道请求处理的结果。
GOF结构

处理者handler处理它所负责的请求,如果可处理则处理,否则将该请求转发给它的后继者
模式特点
稳定点 多个节点的链式处理流程。
变化点 节点的处理的条件或者处理顺序。
扩展点 动态增删处理节点、调整处理顺序
适用点 一个请求被多个对象处理,并且集合对象应被动态指定。
应用:nginx-处理http流程的11个状态。
场景分析
员工请假流程
1 先向部门主管申请,主管进行处理。
2 部门主管无权限处理时再向他的上级申请比如项目主管,项目主管进行处理。
3 项目主管无权限处理时再向他的上级申请比如区域主管,区域主管进行处理。
4 ...申请依次向下传递,像链条一样,直到有管理者有权限处理为止。
代码实现
leave.cpp
引入模式后实现
leave_ex.cpp
测试

结论:
1 将请假流程作为一个链表,每个处理者作为处理节点。
2 从单节点出发,实现处理功能以及链表关系,完成传递功能。
3 从实现上看引入模式后代码量增大不少,但是设定了一个稳定点,后续不管是修改每个处理的条件、处理的顺序、以及增删处理都会比较简单,也更加符合设计原则。而原始代码修改这些需要不停的调整以及增删if else判断。
代码示例
leave.cpp
#include <iostream>
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 <iostream>
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;
};