职责链模式(Chain of Responsibility)
一、责任链模式介绍
责任链模式:将能够处理同一类请求的对象连成一条链,使这些对象都有机会处理请求,所提交的请求沿着链传递。从而避免请求的
发送者和接受者之间的耦合关系。链上的对象逐个判断是否有能力处理该请求,如果能则就处理,如果不能,则传给链上的下一个对象。
直到有一个对象处理它为止。
场景:
1、打牌时,轮流出牌
2、接力赛跑
3、请假审批
4、公文审批
责任链UML图:

Handler:表示处理请求的接口,在这个接口里可以定义链上的下一个继承者,和一个处理请求的抽象方法。
ConcreteHandler1和ConcreteHandler2:表示具体的处理者
二、责任链模式代码实现
这里以请假的流程为例,用责任链模式来实现
首先这里定义一个请假信息的对象
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/** * 请假的基本信息 */public class LeaveRequest { private String empName;//请假人 private int leaveDays;//请假天数 private String reason;//请假理由 public LeaveRequest(String empName, int leaveDays, String reason) { super(); this.empName = empName; this.leaveDays = leaveDays; this.reason = reason; } public String getEmpName() { return empName; } public void setEmpName(String empName) { this.empName = empName; } public int getLeaveDays() { return leaveDays; } public void setLeaveDays(int leaveDays) { this.leaveDays = leaveDays; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } } |
然后定义一个抽象类,来处理各个请求之间的关系。也就是UML图中的Handler部分
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 抽象类:管理责任链上的对象处理的抽象类 */public abstract class Leader { protected String name; protected Leader nextLeader;//下一个继承者 public Leader(String name) { super(); this.name = name; } //设置责任链上的下一个继承者 public void setNextLeader(Leader nextLeader) { this.nextLeader = nextLeader; } //处理请求的抽象方法 public abstract void handleRequest(LeaveRequest leader);} |
接下来就可以开始定义处理请求的具体对象了,比如处理请假信息的:主任,经理,总经理等等。这些对象都必须继承抽象类,来处理请求。
主任对象:处理小于等于3天的假期
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//主任public class Director extends Leader { public Director(String name) { super(name); } /** * 责任链上对象对请求的具体处理 */ @Override public void handleRequest(LeaveRequest leader) { if (leader.getLeaveDays()<=3) { System.out.println("请假人:"+leader.getEmpName()+",天数:"+leader.getLeaveDays()+",理由:"+leader.getReason()); System.out.println("审批人:"+this.name+" 主任,审批通过!"); }else{ if (this.nextLeader != null ) {//如果有下一个继承者 //让下一个继承者处理请求 this.nextLeader.handleRequest(leader); } } }} |
经理对象:处理大于3天,小于等于10天的假期
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//经理public class Manager extends Leader { public Manager(String name) { super(name); } /** * 责任链上对象对请求的具体处理 */ @Override public void handleRequest(LeaveRequest leader) { if (leader.getLeaveDays()<=10) { System.out.println("请假人:"+leader.getEmpName()+",天数:"+leader.getLeaveDays()+",理由:"+leader.getReason()); System.out.println("审批人:"+this.name+" 经理,审批通过!"); }else{ if (this.nextLeader != null ) {//如果有下一个继承者 //让下一个继承者处理请求 this.nextLeader.handleRequest(leader); } } }} |
总经理对象:处理大于等于10天,小于30天的请假信息
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
//总经理public class GeneralManager extends Leader { public GeneralManager(String name) { super(name); } /** * 责任链上对象对请求的具体处理 */ @Override public void handleRequest(LeaveRequest leader) { if (leader.getLeaveDays()<=30) { System.out.println("请假人:"+leader.getEmpName()+",天数:"+leader.getLeaveDays()+",理由:"+leader.getReason()); System.out.println("审批人:"+this.name+" 总经理,审批通过!"); }else{// if (this.nextLeader != null ) {//如果有下一个继承者// //让下一个继承者处理请求// this.nextLeader.handleRequest(leader);// } //总经理上面没人了,所以不往下发送请求。 System.out.println("请假申请,最终不通过!最终审批人:"+this.name+" 总经理"); } }} |
重要代码都写完了,下面开始测试:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public static void main(String[] args) { //构建各个领导人 Leader a = new Director("张三");//主任 Leader b = new Manager("李四");//经理 Leader c = new GeneralManager("王五");//总经理 //设置各个责任链上的关系 a.setNextLeader(b);//主任的下一个审批人为经理 b.setNextLeader(c);//经理的下一个审批人为总经理 //开始请假 LeaveRequest request = new LeaveRequest("小明", 3, "旅游"); a.handleRequest(request);//小明提交了请假申请给主任 } |
控制台则打印:主任审批
请假人:小明,天数:3,理由:旅游
审批人:张三 主任,审批通过!
如果改成13天:则就是总经理审批
请假人:小明,天数:13,理由:旅游
审批人:王五 总经理,审批通过!
此时,我们发现,责任链上漏掉了副总经理,那也很好办。直接加上副总经理就行了
增加一个副总经理的对象
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package com.fz.chainOfResponsibility;/** * 副总经理 */public class ViceGeneralManager extends Leader { public ViceGeneralManager(String name) { super(name); } /** * 责任链上对象对请求的具体处理 */ @Override public void handleRequest(LeaveRequest leader) { if (leader.getLeaveDays()<=20) { System.out.println("请假人:"+leader.getEmpName()+",天数:"+leader.getLeaveDays()+",理由:"+leader.getReason()); System.out.println("审批人:"+this.name+" 副总经理,审批通过!"); }else{ if (this.nextLeader != null ) {//如果有下一个继承者 //让下一个继承者处理请求 this.nextLeader.handleRequest(leader); } } }} |
测试的代码呢,构造副总经理对象。然后再设置继承者的关系
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public static void main(String[] args) { //构建各个领导人 Leader a = new Director("张三");//主任 Leader b = new Manager("李四");//经理 //增加副总经理 Leader b2 = new ViceGeneralManager("赵四");//副总经理 Leader c = new GeneralManager("王五");//总经理 //设置各个责任链上的关系 a.setNextLeader(b);//主任的下一个审批人为经理 b.setNextLeader(b2);//经理的下一个审批人为副总经理 b2.setNextLeader(c);//副总经理的下一个审批人为总经理 //开始请假 LeaveRequest request = new LeaveRequest("小明", 19, "旅游"); a.handleRequest(request);//小明提交了请假申请给主任} |
测试结果就是:副总经理审批
请假人:小明,天数:19,理由:旅游
审批人:赵四 副总经理,审批通过!
三、责任链模式总结
实现方式:
1、链表方式:比如刚才的请假审批
2、非链表方式:通过集合,数组生成责任链更加实用,将链表上的各个对象都添加到集合中,然后通过反射给构建出来。
然后在容器里一个个的处理。(也就是说把测试代码中除了请假的其他代码都给用一个类来处理)
开发中常见场景:
1、Java的异常机制就是一个责任链模式,一个try可以对应多个cathc。如果某一个catch不匹配,则跳到下一个catch中
2、JavaScript语言中的事件的冒泡和捕获机制
3、Servlet开发中,过滤器的链式处理
4、Struts2中,拦截器的调用也是典型的责任链模式
责任链的好处:
1、接受者和发送者都没有对方的明确信息,且链中的对象也并不知道链的结构,结果是责任链可简化对象的相互连接,它们仅需保持一个指向其
后继者的引用,而不需要保持它所有的候选继承者,大大的降低了耦合度。
请求者不用管具体哪个对象会处理,反正该请求肯定会被处理就行了
2、可以随时增加或者修改处理一个请求的结构,增加了给对象指派职责的灵活性
参考资料:
大话设计模式(带目录完整版).pdf
HEAD_FIRST设计模式(中文版).pdf
尚学堂_高淇_java300集最全视频教程_【GOF23设计模式】
职责链模式(Chain of Responsibility)的更多相关文章
- atitit.设计模式(1)--—职责链模式(chain of responsibility)最佳实践O7 日期转换
atitit.设计模式(1)---职责链模式(chain of responsibility)最佳实践O7 日期转换 1. 需求:::日期转换 1 2. 可以选择的模式: 表格模式,责任链模式 1 3 ...
- 设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型)
设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就 ...
- 职责链模式(Chain of Responsibility)(对象行为型)
1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就推卸给另外个一个部门(对象).至于到底谁来解决这个问题呢?政府部门就是为了可以避免屁民的请求与 ...
- 责任链模式 职责链模式 Chain of Responsibility Pattern 行为型 设计模式(十七)
责任链模式(Chain of Responsibility Pattern) 职责链模式 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系 将这些对象连接成一条链,并沿着这 ...
- 设计模式 ( 十二 ) 职责链模式(Chain of Responsibility)(对象行为)
设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决.不能解决就 ...
- 设计模式之职责链模式(Chain of Responsibility)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- 行为型设计模式之职责链模式(Chain of Responsibility)
结构 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 适用性 有多个的对象可以处理一个请求,哪个 ...
- 职责链模式(chain of responsibility)
一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所 ...
- 职责链模式(chain of responsibility Pattern)
职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止. •Handler: 抽象处理者:定义出一个 ...
- C#设计模式——职责链模式(Chain Of Responsibility Pattern)
一.概述 在软件开发中,某一个对象的请求可能会被多个对象处理,但每次最多只有一个对象处理该请求,对这类问题如果显示指定请求的处理对象,那么势必会造成请求与处理的紧耦合,为了将请求与处理解耦,我们可以使 ...
随机推荐
- SQL.Mysql中Cast()函数的用法
比起orcale,MySQL相比之下就简单得多了,只需要一个Cast()函数就能搞定.其语法为:Cast(字段名 as 转换的类型 ),其中类型可以为: CHAR[(N)] 字符型 DATE 日期 ...
- 分享个基于 Node.js + React 的博客系统
是使用 ES2015+ 特性写的,使用了 ThinkJS 框架,后台使用了 React. 完全使用 Markdown 来写文章,还可以把文章推送到团队博客系统中(团队博客也需要使用该系统). 项目地址 ...
- ELK之elasticsearch5.6的安装和head插件的安装
这里选择的elasticsearch为5.6的新版本,根据官方文档有几种暗装方式: https://www.elastic.co/guide/en/elasticsearch/reference/cu ...
- linux 块设备-整理(一)
1. 基本概念: linux设备驱动开发详解(宋宝华): 字符设备与块设备 I/O 操作的不同如下. (1)块设备只能以块为单位接受输入和返回输出,而字符设备则以字节为单位. 大多数设备是字符设备,因 ...
- 聊一聊HTML <!DOCTYPE> 标签
一般一个基本html页面的结构,如下代码所示: <html> <head> <title>我是基本的页面结构</title> </head> ...
- NSURLSession 的学习资料
一个nsurlsession的一些学习资料 http://www.cocoachina.com/ios/20161018/17785.html
- SaltStack高可用multi-master-第十三篇
multi-master官方介绍 As of Salt 0.16.0, the ability to connect minions to multiple masters has been made ...
- CBT怎样进行注册
CBT币未来升值千倍?揭秘为何比特云币注册认证送矿机? 比特云币先机先机,1月6号准备启动,虚拟货币新宠云比特(Cloud Bit 简称CBT)将于近日强势登陆交易市场.这款由全球最大的比特矿工联盟发 ...
- spring boot 使用拦截器,注解 实现 权限过滤
http://www.cnblogs.com/zhangXingSheng/p/7744997.html spring boot 使用拦截器 实现 用户登录拦截 http://www.cnblogs. ...
- C# Page基础功能,用于各页面继承
IBasePage.cs文件 /// <summary> /// 用于页面或用户控件 /// </summary> public interface IBasePage { / ...