责任链模式:
使多个对象都有机会处理请求, 从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条莲,并沿着这条链向下传递请求,直到有一个对象处理它为止。
主要解决:
职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
关键代码:
Handler 里面聚合它自己,在 HanleRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。
应用实例:
1、红楼梦中的”击鼓传花”。
2、JS 中的事件冒泡。
3、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。
优点:
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。
缺点:
1、不能保证请求一定被接收。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
3、可能不容易观察运行时的特征,有碍于除错。
使用场景:
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。
实例:
接下来我们要编写一段代码,在工作中,请假是常有的事,比如某一天,你向你的上级请一天病假,你的经理一般都会给你审批,但是如果你一口气请三天,那么经理就没有权利给你审批了,经理就把你的申请报给上级,也就是你们的总监,总监根据你的实际情况来给你审批,如果你要请7天,估计会把你的申请递给老板,如果你在过分点,请个10几天,估计老板直接给你驳回,并狠狠教训你。在这里我们就能用责任链模式很好的实现这个过程。注意责任链模式,重点的是链这个字,怎么把你的经理,总监,老板链起来很重要。
代码中用的c++来实现
main函数:
#include <iostream>
#include "handler.h"
using namespace std;
int main(int argc, char *argv[])
{
//写请假条
Request request;
request.name = "leiyu";
request.content = "ill";
request.dayNum = 1;
//你的上级
Manager *manager = new Manager;
Majordomo *majordomo = new Majordomo;
Boos *boos = new Boos;
//整理上下级关系
manager->setNextHander(majordomo);
majordomo->setNextHander(boos);
//我把请求先递给经理, 我不用去管他们内部的流程,我只管把请求递给我的直属上级
int dayNumList[] = {1, 3, 7, 10};
for (auto dayNum : dayNumList)
{
request.dayNum = dayNum;
manager->handlerRequest(request);
}
return 0;
}
handler.h文件
#ifndef HANDLER_H
#define HANDLER_H
#include <string>
#include <iostream>
using namespace std;
#define PRINT_REQUES(request)\
std::cout << "---------request----------" << std::endl;\
std::cout << " proposer: " << request.name << std::endl;\
std::cout << " content : " << request.content << std::endl;\
std::cout << " day : " << request.dayNum << std::endl;\
std::cout << "--------------------------" << std::endl;
/**
* @brief The Request class
* //请求类, 包括,申请人, 申请内容,和申请时间
*/
class Request
{
public:
Request(){}
Request(std::string name, std::string content, int dayNum):
name(name), content(content), dayNum(dayNum){}
std::string name; //请假人
std::string content; //请假内容
int dayNum; //请假天数
};
//处理流程的结果,所有 有处理权限的人都要继承这个接口实现处理函数
class Handler
{
private:
Handler *nextHandler; //下个处理人
int level; //当前处理人的权限等级
public://这里
Handler(int level):level(level), nextHandler(NULL){}
void setNextHander(Handler *next)
{
this->nextHandler = next;
}
void handlerRequest(const Request &request)
{
//更具申请天数来判断执行权限
if (this->level >= request.dayNum)
{
doHandler(request); //我有权利执行它
}
else
{
//我没权利,我就把申请传递给上级处理
if (nextHandler != NULL)
{
nextHandler->handlerRequest(request);
}
//否则,就视为不同意
else
{
PRINT_REQUES(request);
std::cout << "No disagree , eject" << endl;
}
}
}
/**
* @brief doHandler 实际的处理
* @param request
*/
virtual void doHandler(const Request &request) = 0;
};
class Manager: public Handler
{
public:
Manager(int level = 1):Handler(level){}
void doHandler(const Request &request)
{
PRINT_REQUES(request);
std::cout << "I`m Manager "
<< "I agress this"
<< std::endl;
}
};
class Majordomo: public Handler
{
public:
Majordomo(int level = 3):Handler(level){}
void doHandler(const Request &request)
{
PRINT_REQUES(request);
std::cout << "I`m Maiordomo "
<< "I agress this"
<< std::endl;
}
};
class Boos: public Handler
{
public:
Boos(int level = 7):Handler(level){}
void doHandler(const Request &request)
{
PRINT_REQUES(request);
std::cout << "I`m Boos"
<< "I agress this"
<< std::endl;
}
};
#endif // HANDLER_H