责任链模式(职责链模式)
目录
一、模式的定义与特点
优点:
缺点:
二、模式的结构与实现
1. 模式的结构
2. 模式的实现
前言:
在现实生活中,一个事件需要经过多个对象处理是很常见的场景。例如,采购审批流程、请假流程等。公司员工请假,可批假的领导有部门负责人、副总经理、总经理等,但每个领导能批准的天数不同,员工必须根据需要请假的天数去找不同的领导签名,也就是说员工必须记住每个领导的姓名、电话和地址等信息,这无疑增加了难度。
在计算机软硬件中也有相关例子,如总线网中数据报传送,每台计算机根据目标地址是否同自己的地址相同来决定是否接收;还有异常处理中,处理程序根据异常的类型决定自己是否处理该异常;还有 Struts2的拦截器、JSP和 Servlet 的 Filter 等,所有这些,都可以考虑使用责任链模式来实现。
一、模式的定义与特点
责任链(Chain of Responsibility)模式的定义:为了避免 请求发送者与多个请求处理者 耦合在一起,于是将所有请求的处理者 通过前一对象记住 其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和请求的处理者解耦了。
优点:
1、降低了对象之间的耦合度。该模式使得一个对象 无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
2、增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
3、增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
4、责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
5、责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点:
1、不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
2、对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
3、职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
二、模式的结构与实现
通常情况下,可以通过数据链表来实现职责链模式的数据结构。
1. 模式的结构
职责链模式主要包含以下角色。
抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与被处理;理解责任链模式应当理解其模式,而不是其具体实现。责任链模式的独到之处是将其节点处理者组合成了链式结构,并允许节点自身决定是否进行请求处理或转发,相当于让请求流动起来。
图1 责任链模式的结构图
2. 模式的实现
职责链模式的实现代码如下:
public class ChainOfResponsibilityPattern {public static void main(String[] args) {//组装责任链Handler handler1 = new ConcreteHandler1();Handler handler2 = new ConcreteHandler2();handler1.setNext(handler2);//提交请求handler1.handleRequest("two");}
}
//抽象处理者角色
abstract class Handler {private Handler next;public void setNext(Handler next) {this.next = next;}public Handler getNext() {return next;}//处理请求的方法public abstract void handleRequest(String request);
}
//具体处理者角色1
class ConcreteHandler1 extends Handler {public void handleRequest(String request) {if (request.equals("one")) {System.out.println("具体处理者1负责处理该请求!");} else {if (getNext() != null) {getNext().handleRequest(request);} else {System.out.println("没有人处理该请求!");}}}
}
//具体处理者角色2
class ConcreteHandler2 extends Handler {public void handleRequest(String request) {if (request.equals("two")) {System.out.println("具体处理者2负责处理该请求!");} else {if (getNext() != null) {getNext().handleRequest(request);} else {System.out.println("没有人处理该请求!");}}}
}
/*
程序运行结果如下:
具体处理者2负责处理该请求!
*//*
在上面代码中,我们把消息硬编码为 String 类型,而在真实业务中,消息是具备多样性的,可以是 int、String 或者自定义类型。因此,在上面代码的基础上,可以对消息类型进行抽象 Request,增强了消息的兼容性。*/
责任链模式(职责链模式)相关推荐
- 责任链模式(职责链模式)(Chain of Responsibility Pattern)
学校OA 系统的采购审批项目:需求是 采购员采购教学器材 如果金额小于等于5000, 由教学主任审批(0<=x<=5000) 如果金额小于等于10000, 由院长审批(5000<x& ...
- 15、设计模式-行为型模式-职责链模式
职责链模式 很多情况下,在一个软件系统中可以处理某个请求的对象不止一个,例如SCM系统中的采购 单审批,主任.副董事长.董事长和董事会都可以处理采购单,他们可以构成一条处理采购 单的链式结构,采购单沿 ...
- 《设计模式详解》行为型模式 - 职责链模式
职责链模式 6.4 职责链模式 6.4.1 概述 6.4.2 结构 6.4.3 案例实现 6.4.4 优缺点 6.4.5 JavaWeb 源码 - FilterChain 完整的笔记目录:<设计 ...
- Java设计模式(备忘录模式-解释器模式-状态模式-策略模式-职责链模式)
Java设计模式Ⅶ 1.备忘录模式 1.1 备忘录模式概述 1.2 代码理解 2.解释器模式 2.1 解释器模式概述 3.状态模式 3.1 状态模式概述 3.2 代码理解 4.策略模式 4.1 策略模 ...
- JS模式--职责链模式
职责链模式的定义:使用多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链, 并沿着这条链条传递下去,直到有一个对象处理它为止. var order500 = f ...
- 5.js模式-职责链模式
1. 职责链模式 将对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止. var chain = function(fn){ this.fn = fn; this.successor = ...
- 十八、职责链模式-推卸责任,不关我的事,我不管!#和设计模式一起旅行#
不在其位,不谋其政! –出自<论语·泰伯> 故事背景 在现实世界中,有很多情况下会遇到一些推卸责任的场景,比如要办理一件事的时候,被告诉你要去做个做这个事情,但是去了这个地方,确告诉要到另 ...
- 职责链模式(Chain of Responsibility)(对象行为型)
1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就推卸给另外个一个部门(对象).至于到底谁来解决这个问题呢?政府部门就是为了可以避免屁民的请求与 ...
- Python设计模式-职责链模式
Python设计模式-职责链模式 代码基于3.5.2,代码如下; #coding:utf-8 #职责链模式class Handler():def __init__(self):self.success ...
- 职责链模式(chain of responsibility)
原文地址 一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不 ...
最新文章
- TextView实现跑马灯效果
- [小技巧]在NTFS分区中复制文件的同时如何复制权限
- linux删除大量文件时遇 -bash: /bin/rm: Argument list too long 错误
- 什么时候该用MySQL,什么时候该用ES呢?
- 2009编程语言排名
- C# 8中的范围类型(Range Type)
- 使用C#和ASP.NET Core的PayPal智能按钮的客户端/服务器实现
- 黑客使用一个UDP数据包可以打开任何HID门禁控制器
- OpenCV-寻找非零点cv::findNonZero
- class 原生js获取父元素_JS获取节点的兄弟,父级,子级元素的方法
- 软件构造 第三章第三节 抽象数据型(ADT)
- 2.原子变量 CAS算法
- Storm 的一个案例
- 计算机考研408复习路线,不再让你头大啦
- 变电站计算机监控 规范,110kV变电站计算机监控系统技术规范书.docx
- 网站跳出率高解决方法
- 物联网云平台的远程管理
- 2021金山wps校招(前端)
- linux sub减法指令出错,sparc的指令的一些总结
- 适合开发人员看的鸿蒙OS介绍~
热门文章
- SWUSTOJ #133 水王争霸
- linux代码对齐快捷键和man帮助文档的使用总结
- 基于linux的qt五子棋小游戏下载,课内资源 - 基于Qt的图形化界面网络在线对战五子棋游戏...
- 饿了么点餐源码、今日头条源码 等
- Python绝技:运用Python成为顶级黑客笔记及心得体会[1]
- 互评Beta版本—博客园安卓APP
- DataWei免费的报表工具,大数据可视化平台
- 搜狗重磅开源的又一力作:一个服务器引擎
- 如何用SQL设计一个图书管理系统<纯SQL>
- 小程序语音红包中遇到的 语音识别silk转wav格式 如何在线转 或者mp3转wav格式...