1、定义
1.1 标准定义
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.(使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。)
1.2 通用类图
责任链模式的核心在“链”上, “链”是由多个处理者ConcreteHandler组成的。
2、实现
2.1 类图
抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由一个抽象类或接口实现。
具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
2.2 代码
2.2.1 Hander类
// Chander.h #include <iostream> class CResponse; class CRequest; class CHander { public: CHander(); ~CHander(); CResponse * mopHandleMessage(CRequest *opRequest); void mvSetNext(CHander *opHander); protected: virtual std::string msGetEcho() = 0; protected: CHander *mopNexthander; int miLevel; }; // 构造三个链成员 class CHander_1 : public CHander { public: CHander_1(); ~CHander_1(); virtual std::string msGetEcho(); }; class CHander_2 : public CHander { public: CHander_2(); ~CHander_2(); virtual std::string msGetEcho(); }; class CHander_3 : public CHander { public: CHander_3(); ~CHander_3(); virtual std::string msGetEcho(); }; // 请求 class CRequest { public: int miNumber; }; // 反馈 class CResponse { public: CResponse(const std::string &sResponse); ~CResponse(); // 获取请求处理结果 std::string msGetResponse(); private: std::string msResponse; };
// Chander.cpp #include "CHander.h" // CHander CHander::CHander() {}; CHander::~CHander(){}; CResponse *CHander::mopHandleMessage(CRequest *opRequest) { if (miLevel == opRequest->miNumber) { return new CResponse(msGetEcho()); } else { if (NULL != mopNexthander) { return mopNexthander->mopHandleMessage(opRequest); } } return new CResponse("No Handle."); } void CHander::mvSetNext(CHander *opHander) { this->mopNexthander = opHander; } // CHander_1 CHander_1::CHander_1() { // 定义级别 miLevel = 1; mopNexthander = NULL; } CHander_1::~CHander_1(){}; std::string CHander_1::msGetEcho() { return "CHander_1 message.\n"; } // CHander_2 CHander_2::CHander_2() { // 定义级别 miLevel = 2; mopNexthander = NULL; } CHander_2::~CHander_2(){}; std::string CHander_2::msGetEcho() { return "CHander_2 message.\n"; } // CHander_3 CHander_3::CHander_3() { // 定义级别 miLevel = 3; mopNexthander = NULL; } CHander_3::~CHander_3(){}; std::string CHander_3::msGetEcho() { return "CHander_3 message.\n"; } //CResponse CResponse::CResponse(const std::string &sResponse) : msResponse(sResponse){} CResponse::~CResponse(){}; std::string CResponse::msGetResponse() { return msResponse; }
2.2.3 调用
#include <iostream> #include "CHander.h" using namespace std; int main() { CHander *opHander1 = new CHander_1; CHander *opHander2 = new CHander_2; CHander *opHander3 = new CHander_3; //构造执行链 opHander1->mvSetNext(opHander2); opHander2->mvSetNext(opHander3); CRequest *opRequest = new CRequest; opRequest->miNumber = 2; CResponse *opResponse = opHander1->mopHandleMessage(opRequest); std::cout << opResponse->msGetResponse().c_str() << endl; delete opResponse; opResponse = NULL; opRequest->miNumber = 1; opResponse = opHander1->mopHandleMessage(opRequest); std::cout << opResponse->msGetResponse().c_str() << endl; delete opResponse; opResponse = NULL; opRequest->miNumber = 4; opResponse = opHander1->mopHandleMessage(opRequest); std::cout << opResponse->msGetResponse().c_str() << endl; delete opResponse; opResponse = NULL; delete opHander1; delete opHander2; delete opHander3; return 0; }
2.2.3 执行结果
3、优缺点
3.1 优点
责任链模式非常显著的优点是将请求和处理分开。请求者可以不用知道是谁处理的,处理者可以不用知道请求的全貌。两者解耦,提高系统的灵活性。
3.2 缺点
责任链有两个非常显著的缺点:一是性能问题,每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题。二是调试不很方便,特别是链条比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂。
3.3 注意
链中节点数量需要控制,避免出现超长链的情况,一般的做法是在Handler中设置一个最大节点数量,在setNext方法中判断是否已经是超过其阈值,超过则不允许该链建立,避免无意识地破坏系统性能。
3.4 总结
在例子和通用源码中CHandler是抽象类, 融合了模板方法模式, 每个实现类只要实现 echo方法处理请求和设置自身级别, 想想单一职责原则和迪米特法则吧, 通过融合模板方法模式, 各个实现类只要关注的自己业务逻辑就成了, 至于说什么事要自己处理, 那就让父类去决定好了, 也就是说父类实现了请求传递的功能, 子类实现请求的处理, 符合单一职责原则, 各个实现类只完成一个动作或逻辑,也就是只有一个原因引起类的改变,在使用的时候用这种方法, 好处是非常明显的了,子类的实现非常简单,责任链的建立也是非常灵活的。
责任链模式屏蔽了请求的处理过程,你发起一个请求到底是谁处理的,这个你不用关心,只要你把请求抛给责任链的第一个处理者, 最终会返回一个处理结果( 当然也可以不做任何处理), 为请求者可以不用知道到底是需要谁来处理的,这是责任链模式的核心,同时责任链模式也可以作为一种补救模式来使用。举个简单例子,如项目开发的时候, 需求确认是这样的:一个请求(如银行客户存款的币种),一个处理者( 只处理人民币),但是随着业务的发展(改革开放了嘛,还要处理美元、日元等),处理者的数量和类型都有所增, 那这时候就可以在第一个处理者后面建立一个链,也就是责任链来处理请求,如果是人民币,好,还是第一个业务逻辑来处理;如果是美元,好,传递到第二个业务逻辑来处理;日元、 欧元……这些都不用在对原有的业务逻辑产生很大改变, 通过扩展实现类就可以很好
地解决这些需求变更的问题。