设计模式之责任链模式(Chain of Responsibility )
责任链的目的是通过特定的设计对请求者和接收者之间进行解耦,请求者调用操作的对象,接收者接收请求并执行相关操作,通过解耦请求者不需要关心接收者的接口,同时也可增强职责的灵活性,通过改变链内的成员或调用次序,允许动态新增或删除责任。
作用
责任链模式通过将多个对象连成链式模式,并沿着这个链传递命令或者请求,直到有对象处理它为止。
类视图

实现
我们还是取比较经典的员工请假的例子。员工为请假的请求者,接收者分别从项目经理、部门经理、公司经理这几个层级,员工向上进行请假操作,首先传递给项目经理,项目经理在处理时分为两种情况,如果项目经理人在公司,并且员工的请假天数满足请假的审批权限范围,则给予审批,反之则申请上级进行处理。
当然我们也可以制定自己的特殊规则,比如经理级别的接收者如果人不在,就不能向上进行请求,比如开可以增加请假的事由以供经理进行判断是否满足请假要求等,这些都可以根据实际情况进行扩充,感兴趣可以自己实现。
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路由(链式)和广播模式(群发)的实现,这下大家就明白了吧;
当然也请注意链式结构的效率问题,对于层级最好还是加以控制。
应用场景
- 基于链式的请求和应答的结构;
- 发送者并不知道在链中的哪个对象会响应请求;
- 责任链中的每一个对象都有职责绝对是否对请求进行响应
设计模式之责任链模式(Chain of Responsibility )的更多相关文章
- 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)
原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of R ...
- 二十四种设计模式:责任链模式(Chain of Responsibility Pattern)
责任链模式(Chain of Responsibility Pattern) 介绍为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求.将这些对象连成一条链,并沿着这条链传递该请求,直 ...
- 设计模式 笔记 责任链模式 chain of responsibility
//---------------------------15/04/25---------------------------- //Chain of responsibility 责任链----- ...
- [设计模式] 13 责任链模式 Chain of Responsibility
转 http://blog.csdn.net/wuzhekai1985 http://www.jellythink.com/archives/878 向项目经理提交了休假申请,我的项目经理向 ...
- 责任链模式-Chain of Responsibility(Java实现), 例2
责任链模式-Chain of Responsibility 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. 咱们在 ...
- 责任链模式-Chain of Responsibility(Java实现), 例1
责任链模式-Chain of Responsibility, 例1 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. ...
- 《JAVA设计模式》之责任链模式(Chain of Responsibility)
在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其 ...
- 责任链模式/chain of responsibility/行为型模式
职责链模式 chain of responsibility 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处 ...
- 设计模式之二十:责任链模式(Chain of Responsibility)
感觉这个设计模式和组合模式一样是一种非常巧妙的设计模式,在须要使用它的地方假设不使用这样的设计模式代码会变的非常复杂,可是这样的设计模式的基本原理又是非常easy的. 责任链模式: 通过使多个对象都有 ...
- C#设计模式-责任链模式(Chain of Responsibility Pattern)
引子 一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程,软件开发中的异常处理流程,web请求处理流程等各种各样的流程,可以考虑使用责任链模式来实现.现在以请假流程为例,一般公 ...
随机推荐
- RobotFramework+Selenium2软件安装教程
1.安装python 必须是 2.7 版本 设置环境变量:F:\software\Python27;F:\software\Python27\Scripts; 重启电脑: 2.安装wxPy ...
- 3 week work—Position
源代码部分: (1)httm部分: <!DOCTYPE html> <html lang="en"> <head> <meta chars ...
- HashSet源码
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java. ...
- centos7系统下,配置学校客户端网络记录
存在的情况 1.学校的网络客户端绑定了个人的电脑MAC地址.绑定了IP地址. 2.我有两台笔记本,一台用了4年多,想用这台(B)直接装centos7系统,然后新买的笔记本(A)做为经常用的,系统为wi ...
- R语言-编写自定义函数 ZZ
一.函数构造器 每一个R函数都包括三个部分:函数名,程序主体以及参数集合,在编写自定义R函数时,需要将三个部分各自储存在一个R对象中.这里需要使用function函数,形如: my_function& ...
- 背水一战 Windows 10 (72) - 控件(控件基类): UIElement - UIElement 的位置, UIElement 的布局, UIElement 的其他特性
[源码下载] 背水一战 Windows 10 (72) - 控件(控件基类): UIElement - UIElement 的位置, UIElement 的布局, UIElement 的其他特性 作者 ...
- confluence与jira账号对接、查看到期时间及问题总结
前面介绍了对于confluence和jira的破解版安装记录,下面简单记录下confluence和jira结合配置:安装顺序:先安装Jira,然后安装Confluence,在Confluence安装过 ...
- JavaScript的BOM编程,事件-第4章
目标 BOM编程 window和document对象 window对象的属性和方法 document对象的属性和方法 JavaScript中对象的分类 浏览器对象:window对象 window对象, ...
- Apple Watch笔记-应用内导航模式
最近苹果婊上市,水果也发布了Xcode 6.2正式版,WatchKit也可以正常使用了.水果很及时地提供了Apple Watch的开发文档,我也及时地尝试着边学习边开发Watch App. 今天主要想 ...
- JS闭包与JS函数
先说说在网上看到的一个闭包案例: var add = (function () {var counter = 0;return function () {return counter += 1;}}) ...