C# · 12月 20, 2021

C++设计模式-责任链模式详解

责任链模式:使多个对象都由机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将所有的可以处理这个请求的对象组成一个责任链,使请求最终可以被执行处理。

作为一个开发人员,在开发过程中经常会遇到与客户或者团队成员之间的交流问题,但是作为一个底层的,有很多时候写代码都是身不由己,需要各种请示。比如客户提出新的需求需要修改代码,需要向技术经理或者架构师提出申请,如何修改;如果客户是功能的修改删除又需要向项目经理提出申请;要是客户提出新的功能需求,还需要向经理请示增加研发经费等等。

但是大家都知道,开发团队在领到自己的任务的时候,往往都是自己闷头苦干,很少关注项目本身意外的问题,突然有一天客户需要修改一个功能模块,准备向架构师提出申请的时候,架构师不在,没法只好向项目经理提出来,但是项目经理正在忙其他的事情,没有时间,最后只能向经理请示。不愧是最后的决策者,当场就决定按照客户的需求来修改。

这样的场景大家肯定会碰到过,遇到问题要首先向自己的上级来申请解决,如果自己的上级有事情,那就向更上一级来申请,一级一级的申请,在中国不可以越级申请的这可是犯了大忌滴(呵呵),最后没有办法只能向经理也就是最大的上级申请,反正无论如何自己的请求一定要得到答复。

这就是责任链,提出的需求最后肯定会在这条链中得到相应的处理。那么如何通过代码来实现这一个过程呢?

1.首先定义请求的类别:

enum MemberLevel {

MEMBER_CODE,//代码级别

MEMBER_PROJECT,//项目级别

MEMBER_BUSINESS,//商务级别

};

2.定义请求的对象,并且给每个请求的对象分配一定的类别:

//请求的内容

class RequestMsg {

public:

RequestMsg(MemberLevel level);

~RequestMsg();

MemberLevel getMemberLevel();

void setMsg(std::string msg);

std::string getMsg();

void setMsgID(int id);

int getMsgID();

private:

MemberLevel _level;

std::string _msg;

int _msgID = 0;

};

RequestMsg::RequestMsg(MemberLevel level) {

_level = level;

}

RequestMsg::~RequestMsg() {

}

MemberLevel RequestMsg::getMemberLevel() {

return _level;

}

void RequestMsg::setMsg(std::string msg) {

_msg = msg;

}

std::string RequestMsg::getMsg() {

return _msg;

}

void RequestMsg::setMsgID(int id) {

_msgID = id;

}

int RequestMsg::getMsgID() {

return _msgID;

}

3.定义接收请求的对象的基类:

class IHandler {

public:

IHandler();

~IHandler();

virtual void process(RequestMsg* request);

virtual void handleMsg(RequestMsg* request);

void setNextHandler(IHandler* nextHandler);

protected:

IHandler* _nextHandler = nullptr;//下一个处理者

MemberLevel _handleLevel;//处理事物的级别

};

IHandler::IHandler() {

}

IHandler::~IHandler() {

}

void IHandler::process(RequestMsg* request) {

if (_handleLevel == request->getMemberLevel()) {

handleMsg(request);

} else {

_nextHandler->process(request);

}

}

void IHandler::handleMsg(RequestMsg* request) {

}

void IHandler::setNextHandler(IHandler* nextHandler) {

_nextHandler = nextHandler;

}

这里面有两个函数:

void setNextHandler(IHandler* nextHandler);

设置下一个处理请求的对象。

virtual void process(RequestMsg* request);

这个函数就是定义了处理的过程,如果请求的级别和当前处理的级别是一样就处理当前的请求,如果处理级别不一致就传递给下一个处理者。

virtual void handleMsg(RequestMsg* request);

每一个继承自这个类的子类都必须实现这个函数,这个函数才是真正处理请求的函数。这个函数实际使用模板的设计模式,把算法结构定义好,子类只需要实现这个函数就可以了。

4.定义处理的子类

第一个子类:代码级别的处理

//代码级别的处理

class CoderHandle : public IHandler {

public:

CoderHandle();

void handleMsg(RequestMsg* request)override;

};

CoderHandle::CoderHandle() {

_handleLevel = MEMBER_CODE;

}

void CoderHandle::handleMsg(RequestMsg* request) {

printf(“软件架构师处理代码的修改!MSGID:%d 消息:%sn”,request->getMsgID(),request->getMsg().c_str());

}

第二个子类:项目级别的处理

//项目级别的处理

class ProjectHandle :public IHandler {

public:

ProjectHandle();

void handleMsg(RequestMsg* request)override;

};

ProjectHandle::ProjectHandle() {

_handleLevel = MEMBER_PROJECT;

}

void ProjectHandle::handleMsg(RequestMsg* request) {

printf(“项目经理处理项目的需求!MSGID:%d 消息:%sn”,request->getMsg().c_str());

}

第三个子类:商务级别的处理

//商务级别的处理

class BusinessHandle :public IHandler {

public:

BusinessHandle();

void handleMsg(RequestMsg* request)override;

};

BusinessHandle::BusinessHandle() {

_handleLevel = MEMBER_BUSINESS;

}

void BusinessHandle::handleMsg(RequestMsg* request) {

printf(“老板处理商务的要求!MSGID:%d 消息:%sn”,request->getMsg().c_str());

}

在以上的三个子类中,他们的构造函数就定义了将要处理的请求的级别,又分别重载了处理请求的函数。

5.请求的发送者基类

class IWorker {

public:

IWorker(std::string name);

~IWorker();

void setRequest(RequestMsg* request);

RequestMsg* getRequest();

std::string getName();

protected:

std::string _name;

RequestMsg* _request;

};

IWorker::IWorker(std::string name) {

_name = name;

}

IWorker::~IWorker() {

}

void IWorker::setRequest(RequestMsg* request) {

_request = request;

}

RequestMsg* IWorker::getRequest() {

return _request;

}

std::string IWorker::getName() {

return _name;

}

6.具体的请求发送者

class ProjectMember :public IWorker {

public:

ProjectMember(std::string name);

};

ProjectMember::ProjectMember(std::string name)

:IWorker(name){

}

请求的发送者只是公有继承而已。里面只有一个构造函数,没有任何其他的函数,因为子类可以直接服用基类的共有方法。

7.使用场景

int main() {

//设置责任链

IHandler* codeHandle = new CoderHandle();

IHandler* projectHandle = new ProjectHandle();

IHandler* businessHandle = new BusinessHandle();

codeHandle->setNextHandler(projectHandle);

projectHandle->setNextHandler(businessHandle);

//项目成员-小明

ProjectMember* xiaoming = new ProjectMember(“小明”);

//小明的请求

RequestMsg* xmRequest = new RequestMsg(MEMBER_CODE);

xmRequest->setMsgID(1);

xmRequest->setMsg(“代码结构混乱,需要重构一下代码结构!”);

xiaoming->setRequest(xmRequest);

codeHandle->process(xmRequest);

//项目成员-小强

ProjectMember* xiaoqiang = new ProjectMember(“小强”);

//小强的请求

RequestMsg* xqRequest = new RequestMsg(MEMBER_BUSINESS);

xqRequest->setMsgID(2);

xqRequest->setMsg(“客户项目需要加大投入,提高预算!”);

xiaoqiang->setRequest(xqRequest);

codeHandle->process(xqRequest);

//项目成员-王工

ProjectMember* wanggong = new ProjectMember(“王工”);

//王工的请求

RequestMsg* wgRequest = new RequestMsg(MEMBER_PROJECT);

wgRequest->setMsgID(3);

wgRequest->setMsg(“客户提出新需求!”);

wanggong->setRequest(wgRequest);

codeHandle->process(wgRequest);

return 0;

}

项目组成员小明向自己的直接上级架构师申请一个代码级别的修改,架构师直接回复了,因为这就是架构师的权限和职责;

项目组成员小强向自己的直接上级结构师申请了一个商务级别的请求,但是这就不是架构师的职责范围,架构师会把请求传递到项目经理,但项目经理也没有商务权限,最后把这个请求传递给最后老板,老板做出了回复;

项目成员王工也向自己的直接上级结构师申请了一个项目级别的请求,架构师没有处理这个请求的权限会把请求传递给项目经理,然后项目经理给出了答复。

所有每一请求都是先向自己的直接上级发出请求,自己的上级无法处理请求时会把这个请求向下一个处理者传递,一直到这个请求被处理为止。

那么这个责任链是如何形成的呢?是通过函数

void setNextHandler(IHandler* nextHandler);

设置的,每一个处理者都会设置自己的下一个处理者,当自己的处理不了当前级别的请求时,就会传递给下一个处理者。

运行结果:

责任链模式的优点:将请求和处理者分开,提高系统的灵活性;

但是一定要控制这个责任链的长度,否则会有效率的问题。责任链处理请求都是从开头第一个处理者开始,直到遇到可以处理这个请求的处理者位置,如果责任链很长的话,每次处理请求会重复以上的过程,整体的效率会降低。