您的位置:首页 > 其它

【设计模式】责任链模式

2017-07-28 00:16 309 查看

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方法处理请求和设置自身级别, 想想单一职责原则和迪米特法则吧, 通过融合模板方法模式, 各个实现类只要关注的自己业务逻辑就成了, 至于说什么事要自己处理, 那就让父类去决定好了, 也就是说父类实现了请求传递的功能, 子类实现请求的处理, 符合单一职责原则, 各个实现类只完成一个动作或逻辑,也就是只有一个原因引起类的改变,在使用的时候用这种方法, 好处是非常明显的了,子类的实现非常简单,责任链的建立也是非常灵活的。责任链模式屏蔽了请求的处理过程,你发起一个请求到底是谁处理的,这个你不用关心,只要你把请求抛给责任链的第一个处理者, 最终会返回一个处理结果( 当然也可以不做任何处理), 为请求者可以不用知道到底是需要谁来处理的,这是责任链模式的核心,同时责任链模式也可以作为一种补救模式来使用。举个简单例子,如项目开发的时候, 需求确认是这样的:一个请求(如银行客户存款的币种),一个处理者( 只处理人民币),但是随着业务的发展(改革开放了嘛,还要处理美元、日元等),处理者的数量和类型都有所增, 那这时候就可以在第一个处理者后面建立一个链,也就是责任链来处理请求,如果是人民币,好,还是第一个业务逻辑来处理;如果是美元,好,传递到第二个业务逻辑来处理;日元、 欧元……这些都不用在对原有的业务逻辑产生很大改变, 通过扩展实现类就可以很好的解决这些需求的变更问题。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: