设计模式---数据结构模式之职责链模式(Chain of Responsibility)
一:概念
职责链模式(CoR,Chain of Responsibility)是行为模式之一,该模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的对象之间像链条一样紧密相连,所以被称作职责链模式。
例1:比如客户Client要完成一个任务,这个任务包括a,b,c,d四个部分。
首先客户Client把任务交给A,A完成a部分之后,把任务交给B,B完成b部分,…,直到D完成d部分。
例2:比如政府部分的某项工作,县政府先完成自己能处理的部分,不能处理的部分交给省政府,省政府再完成自己职责范围内的部分,不能处理的部分交给中央政府,中央政府最后完成该项工作。
例3:软件窗口的消息传播。
例4:SERVLET容器的过滤器(Filter)框架实现。
二:动机
在软件构建的过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少的带来请求发送者与接受者的耦合。
如何使请求的发送者不需要指定具体的接受者?让请求的接受者自己在运行时决定来处理请求,从而使两者解耦。
三:模式定义
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链(链表),并沿着这条链传递请求,直到有一个对象处理它为止。
——《设计模式》GoF
四:代码讲解
(一)Request对象:携带请求信息
class Reqest
{
string description;
RequestType reqType;
public:
Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {}
RequestType getReqType() const { return reqType; }
const string& getDescription() const { return description; }
};
(二)ChainHandler基类处理者:
class ChainHandler{
ChainHandler *nextChain; //多态指针指向自己,形成了多态链表
void sendReqestToNextHandler(const Reqest & req) //若是我的链表的下一个结点不为空,那么久传递给下一个结点进行处理
{
if (nextChain != nullptr)
nextChain->handle(req);
}
protected:
virtual bool canHandleRequest(const Reqest & req) = 0; //判断请求能否处理,运行时判断
virtual void processRequest(const Reqest & req) = 0; //具体处理业务逻辑
public:
ChainHandler() { nextChain = nullptr; }
void setNextChain(ChainHandler *next) { nextChain = next; } //建立链表
void handle(const Reqest & req) //调用方法处理逻辑,当前无法处理,使用下一个
{
if (canHandleRequest(req))
processRequest(req);
else
sendReqestToNextHandler(req);
}
};
(三)Handler具体处理对象
class Handler1 : public ChainHandler{
protected:
bool canHandleRequest(const Reqest & req) override
{
return req.getReqType() == RequestType::REQ_HANDLER1;
}
void processRequest(const Reqest & req) override
{
cout << "Handler1 is handle reqest: " << req.getDescription() << endl;
}
};
class Handler2 : public ChainHandler{
protected:
bool canHandleRequest(const Reqest & req) override
{
return req.getReqType() == RequestType::REQ_HANDLER2;
}
void processRequest(const Reqest & req) override
{
cout << "Handler2 is handle reqest: " << req.getDescription() << endl;
}
};
class Handler3 : public ChainHandler{
protected:
bool canHandleRequest(const Reqest & req) override
{
return req.getReqType() == RequestType::REQ_HANDLER3;
}
void processRequest(const Reqest & req) override
{
cout << "Handler3 is handle reqest: " << req.getDescription() << endl;
}
};
(四)构建链表
int main(){
Handler1 h1;
Handler2 h2;
Handler3 h3;
h1.setNextChain(&h2); //构建链表
h2.setNextChain(&h3);
Reqest req("process task ... ", RequestType::REQ_HANDLER3); //获取请求,设置类型
h1.handle(req); //处理请求
return ;
}
五:类图(结构)

职责链模式在现在C++中使用不多。但是这种思想还是值得借鉴,比如在python中Django框架数据添加扩展中提到的也是这样的,只要前面不抛出异常,就接着执行
六:要点总结
(一)Chain of Responsibility模式的应用场合在于“一个请求可能有多个接受者,但是最后真正接受者只有一个”,这时候请求发送者与接受者的耦合可能出现“变化脆弱”的症状,职责链的目的就是将二者解耦,从而更好的应对变化。
(二)应用了Chain of Responsibility模式后,对象的职责分派将更具灵活性。我们可以在运行时动态添加/修改请求的处理指责。
(三)如果请求传递到职责链的末尾仍得不到处理,应该有一个合理的缺省机制。这也是每一个接受者对象的责任,而不是发出请求的对象的责任。
七:案例实现(代码样例)
#include <iostream>
#include <string> using namespace std; enum class RequestType
{
REQ_HANDLER1,
REQ_HANDLER2,
REQ_HANDLER3
}; class Reqest
{
string description;
RequestType reqType;
public:
Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {}
RequestType getReqType() const { return reqType; }
const string& getDescription() const { return description; }
}; class ChainHandler{ ChainHandler *nextChain;
void sendReqestToNextHandler(const Reqest & req)
{
if (nextChain != nullptr)
nextChain->handle(req);
}
protected:
virtual bool canHandleRequest(const Reqest & req) = ;
virtual void processRequest(const Reqest & req) = ;
public:
ChainHandler() { nextChain = nullptr; }
void setNextChain(ChainHandler *next) { nextChain = next; } void handle(const Reqest & req)
{
if (canHandleRequest(req))
processRequest(req);
else
sendReqestToNextHandler(req);
}
}; class Handler1 : public ChainHandler{
protected:
bool canHandleRequest(const Reqest & req) override
{
return req.getReqType() == RequestType::REQ_HANDLER1;
}
void processRequest(const Reqest & req) override
{
cout << "Handler1 is handle reqest: " << req.getDescription() << endl;
}
}; class Handler2 : public ChainHandler{
protected:
bool canHandleRequest(const Reqest & req) override
{
return req.getReqType() == RequestType::REQ_HANDLER2;
}
void processRequest(const Reqest & req) override
{
cout << "Handler2 is handle reqest: " << req.getDescription() << endl;
}
}; class Handler3 : public ChainHandler{
protected:
bool canHandleRequest(const Reqest & req) override
{
return req.getReqType() == RequestType::REQ_HANDLER3;
}
void processRequest(const Reqest & req) override
{
cout << "Handler3 is handle reqest: " << req.getDescription() << endl;
}
}; int main(){
Handler1 h1;
Handler2 h2;
Handler3 h3;
h1.setNextChain(&h2);
h2.setNextChain(&h3); Reqest req("process task ... ", RequestType::REQ_HANDLER3);
h1.handle(req); system("pause");
return ;
}
全部代码

八:案例实现(处理汽车)
(一)handle基类实现
class CarHandler
{
protected:
CarHandler* nextHandler;
public:
virtual void HandlerCar() = ;
public:
CarHandler* SetNextHandler(CarHandler* hand)
{
this->nextHandler = hand;
return this->nextHandler;
} virtual ~CarHandler(){}
};
(二)实现具体处理子类
class CarHandleHead :public CarHandler
{
public:
virtual void HandlerCar()
{
cout << "composite car head" << endl;
if (nextHandler != NULL)
nextHandler->HandlerCar();
}
}; class CarHandleBody :public CarHandler
{
public:
virtual void HandlerCar()
{
cout << "composite car body" << endl;
if (nextHandler != NULL)
nextHandler->HandlerCar();
}
}; class CarHandleTail :public CarHandler
{
public:
virtual void HandlerCar()
{
cout << "composite car tail" << endl;
if (nextHandler != NULL)
nextHandler->HandlerCar();
}
};
(三)组合责任链,开始演示
void main()
{
CarHandler* CH = new CarHandleHead();
CarHandler* CB = new CarHandleBody();
CarHandler* CT = new CarHandleTail(); CH->SetNextHandler(CB);
CB->SetNextHandler(CT); CH->HandlerCar(); delete CH;
delete CB;
delete CT; system("pause");
return;
}

设计模式---数据结构模式之职责链模式(Chain of Responsibility)的更多相关文章
- 设计模式的征途—14.职责链(Chain of Responsibility)模式
相信大家都玩过类似于“斗地主”的纸牌游戏,某人出牌给他的下家,下家看看手中的牌,如果要不起,则将出牌请求转发给他的下家,其下家再进行判断.一个循环下来,如果其他人都要不起该牌,则最初的出牌者可以打出新 ...
- atitit.设计模式(1)--—职责链模式(chain of responsibility)最佳实践O7 日期转换
atitit.设计模式(1)---职责链模式(chain of responsibility)最佳实践O7 日期转换 1. 需求:::日期转换 1 2. 可以选择的模式: 表格模式,责任链模式 1 3 ...
- js设计模式——6.模板方法模式与职责链模式
js设计模式——6.模板方法模式与职责链模式 职责链模式
- C#设计模式之二十一职责链模式(Chain of Responsibility Pattern)【行为型】
一.引言 今天我们开始讲"行为型"设计模式的第八个模式,该模式是[职责链模式],英文名称是:Chain of Responsibility Pattern.让我们看看现实生活中 ...
- C#设计模式之二十职责链模式(Chain of Responsibility Pattern)【行为型】
一.引言 今天我们开始讲“行为型”设计模式的第八个模式,该模式是[职责链模式],英文名称是:Chain of Responsibility Pattern.让我们看看现实生活中的例子吧,理解起来可能更 ...
- 重温设计模式(三)——职责链模式(chain of responsibility)
一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所 ...
- 设计模式24---设计模式之职责链模式(Chain of Responsibility)(行为型)
1.职责链模式讲解 1.1职责链定义 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 1.2职责链模式 ...
- javascript设计模式学习之十三——职责链模式
一.职责链的定义和使用场景 职责链模式的定义是,职责链模式将一系列可能会处理请求的对象连接成一条链,请求在这些对象之间一次传递,直到遇到一个可以处理它的对象.从而避免请求的发送者和接收者之间的耦合关系 ...
- 行为型模式(八) 职责链模式(Chain of Responsibility)
一.动机(Motivate) 在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少地带来请求发送者与接受者的紧耦合.如何使请求的发送者不需要指定 ...
随机推荐
- #194 sequence(搜索+动态规划+主席树)
考虑按顺序暴搜子序列.如果序列中的数两两不同,显然每次给上一个找到的子序列添上后缀最小值,即为下一个要找的子序列.如果不能再加了就回溯继续考虑后缀次小.第三小……值,直到找到k个子序列. 有重复的数后 ...
- Android短信大全
使用ListView实现点击条目跳转短信界面,并将内容传至短信页面: 代码如下:activity_main.xml: <?xml version="1.0" encoding ...
- 记一次Java调优案例分析
上周,一同学给我发来,他们那里的案例 一看就是新生代产生过多对象,肯定是批量或者循环操作导致的,导致新生代一直在进行回收导致. 如果是老生代出现这样的问题,大部分情况下是列表或者集合导致的. 因此我们 ...
- MT【252】椭圆内接三角形内切圆半径
已知椭圆$\dfrac{{{x^2}}}{{{a^2}}} + \dfrac{{{y^2}}}{{{b^2}}} = 1$($a > b > 0$),${F_1}$.${F_2}$为其左右 ...
- 使用nmon监控Linxu服务器性能
nmon是IBM开发的Linux软件工具.能够监控多项Linux服务,最常见的如:CPU使用率.内存使用率.硬盘读写.网卡流量等. 并能设置参数,将记录的数据保存到文件,利用Excel做统计分析. 安 ...
- 【BZOJ5304】[HAOI2018]字串覆盖(后缀数组,主席树,倍增)
[BZOJ5304][HAOI2018]字串覆盖(后缀数组,主席树,倍增) 题面 BZOJ 洛谷 题解 贪心的想法是从左往右,能选就选.这个显然是正确的. 题目的数据范围很好的说明了要对于询问分开进行 ...
- JavaWeb项目:在线评测系统
此项目为本人的Java大作业. 项目文件和相关资源已上传到本人的GitHub 一.项目概况 1.1设计内容 一个在线评测系统,分用户和管理员两种身份.用户能够通过注册登录,参加比赛,最后实时得到比赛结 ...
- luogu4145 上帝造题的七分钟2 (线段树)
题意:给一个数列,维护两个操作,区间开根号.询问区间和 注意到1e12开根号六次后就变成1,而且根号1等于1 也就是说,就算我们用单点修改,只要跳过1,那么修改的次数最多也就是6n 那么维护一个区间最 ...
- 关于windows下NODE_ENV=test无效的情况解决办法
redux的单元测试命令为 NODE_ENV=test mocha --recursive --compilers js:babel-core/register --require ./test/se ...
- 使用ajax实现前后端是数据交互
ajax的概念 ajax一个前后台配合的技术,它可以让javascript发送http请求,与后台通信,获取数据和信息.ajax技术的原理是实例化xmlhttp对象,使用此对象与后台通信.jquery ...