简介
责任链模式是一种设计模式(行为模式)。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
角色
Handler(抽象处理者):定义出一个处理请求的接口。接口定义出一个方法以设定和返回对下家的引用。
ConcreteHandler(具体处理者):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
图解
优点
降低耦合度。它将请求的发送者和接收者解耦。
简化了对象。使得对象不需要知道链的结构。
增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
增加新的请求处理类很方便。
缺点
能保证请求一定被接收。
系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
可能不容易观察运行时的特征,有碍于除错。
应用场景
有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
可动态指定一组对象处理请求。
实例
员工请假时,不同的时长需要不同的管理人员批准。小于2h,项目经理可以直接批准;大于等于2h但小于24h,项目经理需要上报项目主管,项目主管可以直接批准;大于等于24h,项目主管需要上报部门经理,部门经理做出最终决定。
handler.h
#ifndef _HANDLER_H_
#define _HANDLER_H_
#include <iostream>
class Handler{
public:
Handler() {
next = nullptr;
}
virtual ~Handler() {
if (next != nullptr) {
delete next;
next = nullptr;
}
}
void SetNext(Handler *next) {
this->next = next;
}
virtual void HandleRequest(int hour) = 0;
protected:
Handler *next;
};
#endif // _HANDLER_H_
- concrete_handler.h
#ifndef _CONCRETE_HANDLER_H_
#define _CONCRETE_HANDLER_H_
#include "handler.h"
using namespace std;
class PM : public Handler{
public:
PM() {}
~PM() {}
void HandleRequest(int hour) {
if (hour < 2) {
cout << "PM同意了你" << hour << "小时的假" << endl;
}
else {
next->HandleRequest(hour);
}
}
};
class ProjectLeader : public Handler{
public:
ProjectLeader() {}
~ProjectLeader() {}
void HandleRequest(int hour) {
if (hour < 24) {
cout << "ProjectLeader同意了你" << hour << "小时的假" << endl;
}
else {
next->HandleRequest(hour);
}
}
};
class DepartmentManager : public Handler{
public:
DepartmentManager() {}
~DepartmentManager() {}
void HandleRequest(int hour) {
if (hour < 48) {
cout << "DepartmentManager同意了你" << hour << "小时的假" << endl;
}
else {
cout << "你的请假申请未被批准" << endl;
}
}
};
#endif // _CONCRETE_HANDLER_H_
- main.cpp
#include "concrete_handler.h"
int main(int argc,char* argv[]){
Handler *pm = new PM();
Handler *projectleader = new ProjectLeader();
Handler *departmentmanager = new DepartmentManager();
// 职责链:项目经理 -> 项目主管 -> 部门经理
pm->SetNext(projectleader);
projectleader->SetNext(departmentmanager);
pm->HandleRequest(1);
pm->HandleRequest(23);
pm->HandleRequest(48);
getchar();
return 0;
}
- 运行结果