责任链的目的是通过特定的设计对请求者和接收者之间进行解耦,请求者调用操作的对象,接收者接收请求并执行相关操作,通过解耦请求者不需要关心接收者的接口,同时也可增强职责的灵活性,通过改变链内的成员或调用次序,允许动态新增或删除责任。

作用

责任链模式通过将多个对象连成链式模式,并沿着这个链传递命令或者请求,直到有对象处理它为止。

类视图

实现

我们还是取比较经典的员工请假的例子。员工为请假的请求者,接收者分别从项目经理、部门经理、公司经理这几个层级,员工向上进行请假操作,首先传递给项目经理,项目经理在处理时分为两种情况,如果项目经理人在公司,并且员工的请假天数满足请假的审批权限范围,则给予审批,反之则申请上级进行处理。

当然我们也可以制定自己的特殊规则,比如经理级别的接收者如果人不在,就不能向上进行请求,比如开可以增加请假的事由以供经理进行判断是否满足请假要求等,这些都可以根据实际情况进行扩充,感兴趣可以自己实现。

class DayOffRequest
{
public:
DayOffRequest(int hour)
:m_iHour(hour)
{}
int GetHour()
{
return m_iHour;
}
private:
int m_iHour;
}; class Manager
{
public:
virtual bool HandleRequest(DayOffRequest* request) = 0;
}; class PM : public Manager //Project manager项目经理
{
public:
PM(Manager* handler)
:m_Handler(handler)
{}
bool HandleRequest(DayOffRequest* request)
{
//在权责范围内给予批准
if (request->GetHour() <= 2)
{
cout << "PM said : OK" << endl;
return true;
}
else if (m_Handler) //请求上级
{
return m_Handler->HandleRequest(request);
}
else
{
//无法定夺
cout <<"PM said :no decide" << endl;
return false;
}
}
private:
Manager* m_Handler;
}; class DM : public Manager //Department Manager部门经理
{
public:
DM(Manager* handler)
:m_handler(handler)
{}
bool HandleRequest(DayOffRequest* request)
{
if (m_Handler)
{
if(request->getHour() <=16)
{
cout <<"DM said :OK" << endl;
return true;
}
else
return m_Handler->HandleRequest(request);
}
else
{
cout <<"DM said :no decide" << endl;
return false;
}
}
private:
Manager *m_handler;
}; class GM : public Manager //General Manager 总经理
{
public:
GM():m_handler(NULL) {}
bool IsInCompany()
{
return static_cast<bool>(rand()%2) ;
}
bool HandleRequest(DayOffRequest* request)
{
if(IsInCompany())
{
cout <<"GM said :OK" << endl;
return true;
}
else
{
cout <<"GM said :try again latter" << endl;
return false;
} }
private:
Manager* m_handler;
};
int main()
{
Manager *general = new GM();
Manager *department = new DM(general); //设置上级
Manager *project = new PM(department); //设置上级 DayOffRequest reqsta(2); //一个员工请假2小时
project->DealWithRequest(&reqsta);
DayOffRequest reqstb(20); //另一个员工请假20小时
project->DealWithRequest(&reqstb); delete project;
delete department;
delete general;
}

责任链和观察者模式比较相像,都是进行命令和数据的传递,二者的关键区别是一个是有明确层级和先后关系(也可能不是那么明显),而一个是对象平等的,最通俗的例子就是网络中的DNS路由(链式)和广播模式(群发)的实现,这下大家就明白了吧;

当然也请注意链式结构的效率问题,对于层级最好还是加以控制。

应用场景

  1. 基于链式的请求和应答的结构;
  2. 发送者并不知道在链中的哪个对象会响应请求;
  3. 责任链中的每一个对象都有职责绝对是否对请求进行响应

设计模式之责任链模式(Chain of Responsibility )的更多相关文章

  1. 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)

    原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of R ...

  2. 二十四种设计模式:责任链模式(Chain of Responsibility Pattern)

    责任链模式(Chain of Responsibility Pattern) 介绍为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求.将这些对象连成一条链,并沿着这条链传递该请求,直 ...

  3. 设计模式 笔记 责任链模式 chain of responsibility

    //---------------------------15/04/25---------------------------- //Chain of responsibility 责任链----- ...

  4. [设计模式] 13 责任链模式 Chain of Responsibility

    转    http://blog.csdn.net/wuzhekai1985   http://www.jellythink.com/archives/878 向项目经理提交了休假申请,我的项目经理向 ...

  5. 责任链模式-Chain of Responsibility(Java实现), 例2

    责任链模式-Chain of Responsibility 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. 咱们在 ...

  6. 责任链模式-Chain of Responsibility(Java实现), 例1

    责任链模式-Chain of Responsibility, 例1 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. ...

  7. 《JAVA设计模式》之责任链模式(Chain of Responsibility)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其 ...

  8. 责任链模式/chain of responsibility/行为型模式

    职责链模式 chain of responsibility 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处 ...

  9. 设计模式之二十:责任链模式(Chain of Responsibility)

    感觉这个设计模式和组合模式一样是一种非常巧妙的设计模式,在须要使用它的地方假设不使用这样的设计模式代码会变的非常复杂,可是这样的设计模式的基本原理又是非常easy的. 责任链模式: 通过使多个对象都有 ...

  10. C#设计模式-责任链模式(Chain of Responsibility Pattern)

    引子 一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程,软件开发中的异常处理流程,web请求处理流程等各种各样的流程,可以考虑使用责任链模式来实现.现在以请假流程为例,一般公 ...

随机推荐

  1. Springboot+Mybatis+MySQL实例练习时踩坑记录

    最近刚开始学习后端,直接让上手学习Springboot+Mybatis+MySQL对CRUD的实例,虽然实例不难,但是上面的三个知识我都不懂,就有点为难我了 所以经常遇到一个点卡自己很久的情况,这里列 ...

  2. Vuejs——(9)组件——props数据传递

    版权声明:出处http://blog.csdn.net/qq20004604   目录(?)[+]   本篇资料来于官方文档: http://cn.vuejs.org/guide/components ...

  3. Explain Shell 网站(解释各种Shell命令)

    [Explain Shell 网站] 调用语法: https://explainshell.com/explain?cmd= shell命令 示例 结果如下图:

  4. 利用phpcms后台漏洞渗透某色情网站

    本文来源于i春秋学院,未经允许严禁转载 phpcms v9版本最近爆了好几个漏洞,网上公开了不少信息,但没有真正实战过,就不能掌握其利用方法,本次是在偶然的机会下,发现一个网站推荐楼凤信息,通过分析, ...

  5. 怎样提供一个好的移动API接口服务/从零到一[开发篇]

    引语:现在互联网那么热,你手里没几个APP都不好意思跟别人打招呼!但是,难道APP就是全能的神吗?答案是否定的,除了优雅的APP前端展示,其实核心还是服务器端.数据的保存.查询.消息的推送,无不是在服 ...

  6. Shell-3--变量

    用户自定义变量 环境变量 位置参数变量 预定义变量

  7. debian安装tftp服务

    步骤1:安装 apt-get install tftp-hpa tftpd-hpa tftp-hpa是client,tftpd-hpaserver 步骤2:建立tftp目录 mkdir /tftpbo ...

  8. linux下把动态链接库加入环境变量的几种方式

    一. 将网络SDK各动态库路径加入到LD_LIBRARY_PATH环境变量 1.在终端输入:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/XXX 只在当前终端起作用 ...

  9. Spring Boot Runner启动器

    Runner启动器 如果你想在Spring Boot启动的时候运行一些特定的代码,你可以实现接口ApplicationRunner或者CommandLineRunner,这两个接口实现方式一样,它们都 ...

  10. jenkins 集成钉钉机器人通知

    公司使用钉钉做为公司内部的通讯工具,所以想通过Jenkins发布完成以后通过钉钉来通知大家,研究发现钉钉提供机器人,所以我把机器人集成进来通知相关人员. 1.创建通知人群组,添加机器人(钉钉默认自带了 ...