当前位置: 首页 > 编程日记 > 正文

Chain of Responsibility 责任链模式 MD

责任链模式

简介

责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链,请求在这个链上【传递】,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

责任链模式屏蔽了请求的处理过程,你发起一个请求到底是谁处理的,这个你不用关心,只要你把请求抛给责任链的第一个处理者,最终会返回一个处理结果(当然也可以不做任何处理),作为请求者可以不用知道到底是需要谁来处理的,这是责任链模式的核心。

责任链就是从一个起点发起请求,然后沿着任务链依次传递给每一个节点上的对象,直到有一个节点处理这个请求为止。

使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

现实中最适合责任链的应该就是部门领导之间的上报请求了。比如员工要申请一笔资金,会先向组长申请,额度如果在组长的范围内,组长就批了,组长权限不够就向主管申请,主管如果也额度不够就向经理申请。这就形成了个责任链。

组长,主管,经理。每个人都是责任链上的一个节点。一个请求被层层转达,直到被处理或没有一个人能处理。普通员工,就是那个申请的发起者,并不需要知道到底最后是谁审批的,他只要拿到钱就行了。这样就造成了请求者和处理者的解耦。

责任链有一个缺点是,大家在开发的时候要注意,调试不是很方便,特别是链条比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂。

适用性

  • 有多个对象可以处理一个请求,具体哪个对象处理该请求在运行时刻自动确定。
  • 在请求的处理者不明确的情况下,向多个对象的一个提交请求。
  • 需要动态指定一组对象处理请求。

角色

  • Handler:抽象处理者角色,声明一个处理请求的方法,并保持对下一个处理节点Handler对象的引用。
  • ConcreteHandler: 具体的处理者,对请求进行处理,如果不处理就讲请求转发给下一个节点上的处理对象。

作用:请求会被链上的对象处理,但是客户端不知道请求会被哪些对象处理
通过把请求从一个对象传递到链条中下一个对象的方式,直到请求被处理完毕,以实现对象间的解耦。

JDK中体现:ClassLoader的委托模型

简单版案例

抽象处理者:

1 public abstract class Handler {
2    protected Handler successor;
3    public abstract void handleRequest(String condition);
4 }


实际处理者1

public class ConcreteHandler1 extends Handler {@Overridepublic void handleRequest(String condition) {if ("ConcreteHandler1".equals(condition)){System.out.println("ConcreteHandler1 handled");}else {successor.handleRequest(condition);}}
}


实际处理者2

public class ConcreteHandler2 extends Handler {@Overridepublic void handleRequest(String condition) {if ("ConcreteHandler2".equals(condition)) {System.out.println("ConcreteHandler2 handled");} else {successor.handleRequest(condition);}}
}


客户端调用,组成一条责任链

public class Client {public static void main(String[] args) {ConcreteHandler1 concreteHandler1 = new ConcreteHandler1();ConcreteHandler2 concreteHandler2 = new ConcreteHandler2();concreteHandler1.successor = concreteHandler2;concreteHandler2.successor = concreteHandler1;concreteHandler1.handleRequest("ConcreteHandler2");}
}

简单版中,传递的都是统一的字符串,处理也比较简单。但是在实际开发中,责任链中的请求处理规则是不尽相同的,这种时候需要对请求进行封装,同时对请求的处理规则也进行一个封装,

复杂版案例

抽象处理者

public abstract class AbstractHandler {protected AbstractHandler nextHandler;
​public final void handleRequest(AbstractRequest request){if (request.getRequestLevel()==getHandleLevel()){handle(request);}else {if (nextHandler!=null){nextHandler.handleRequest(request);}else {System.out.println("没有对象能处理这个请求");}}}protected abstract int getHandleLevel();protected abstract void handle(AbstractRequest request);
}


三个处理者

public class Handler1 extends AbstractHandler {@Overrideprotected int getHandleLevel() {return 1;}
​@Overrideprotected void handle(AbstractRequest request) {System.out.println("Handler1处理了请求:"+request.getRequestLevel());}
}
public class Handler2 extends AbstractHandler {@Overrideprotected int getHandleLevel() {return 2;} ​@Overrideprotected void handle(AbstractRequest request) {System.out.println("Handler2处理了请求:"+request.getRequestLevel());} }
public class Handler3 extends AbstractHandler {@Overrideprotected int getHandleLevel() {return 3;} ​@Overrideprotected void handle(AbstractRequest request) {System.out.println("Handler3处理了请求:"+request.getRequestLevel());} }


抽象请求者

public abstract class AbstractRequest {private Object obj;public AbstractRequest(Object obj){this.obj=obj;}public Object getContent(){return obj;}public abstract int getRequestLevel();
}


实现的三个请求

public class Request1 extends AbstractRequest {public Request1(Object obj) {super(obj);}
​@Overridepublic int getRequestLevel() {return 1;}
}
public class Request2 extends AbstractRequest {public Request2(Object obj) {super(obj);}
​@Overridepublic int getRequestLevel() {return 2;}
}
public class Request3 extends AbstractRequest {public Request3(Object obj) {super(obj);}
​@Overridepublic int getRequestLevel() {return 3;}
}


客户端调用

public class Client {public static void main(String[] args) {//构造三个处理对象AbstractHandler handler1 = new Handler1();AbstractHandler handler2 = new Handler2();AbstractHandler handler3 = new Handler3();//串成一个责任链handler1.nextHandler = handler2;handler2.nextHandler = handler3;//构造三个请求AbstractRequest request1 = new Request1("A");AbstractRequest request2 = new Request2("B");AbstractRequest request3 = new Request3("C");
​handler1.handleRequest(request1);handler1.handleRequest(request2);handler1.handleRequest(request3);}
}


实际案例

抽象的领导

public abstract class Leader {protected Leader nextLeader;
​public final void handleRequest(int money) {if (money < = getLimit()) {handle(money);} else {if (nextLeader != null) {nextLeader.handleRequest(money);} else {System.out.println(money + "没人能批准");}}}
​public abstract int getLimit();
​public abstract void handle(int money);
}


三个具体的领导

public class GroupLeader extends Leader {@Overridepublic int getLimit() {return 5000;}
​@Overridepublic void handle(int money) {System.out.println(money + "由组长批准");}
}public class Director extends Leader {@Overridepublic int getLimit() {return 10000;}
​@Overridepublic void handle(int money) {System.out.println(money + "由主管批准");}
}public class Manager extends Leader {@Overridepublic int getLimit() {return 20000;}
​@Overridepublic void handle(int money) {System.out.println(money + "由经理批准");}
}


员工申请:

public class Test {public static void main(String[] args) {Leader groupLeader = new GroupLeader();Leader director = new Director();Leader manager = new Manager();groupLeader.nextLeader = director;director.nextLeader = manager;
​groupLeader.handleRequest(4000);groupLeader.handleRequest(12000);groupLeader.handleRequest(30000);}
}


2016-04-21

转载于:https://www.cnblogs.com/baiqiantao/p/5417291.html

相关文章:

python tkinter选择路径控件_Python3 Tkinter选择路径功能的实现方法

效果基于Python3。 在自己写小工具的时候因为这个功能纠结了一会儿&#xff0c;这里写个小例子&#xff0c;供有需要的参考。 小例子&#xff0c;就是点击按钮打开路径选择窗口&#xff0c;选择后把值传给Entry输出。 效果预览 这是选择前&#xff1a;选择&#xff1a;选择后&a…

Golang TDD实践报告:快速排序Quick Sort

Golang TDD实践报告&#xff1a;快速排序Quick Sort 【阅读时间&#xff1a;约5分钟】0.项目需求1.编写符合项目输入输出的一个测试2.尝试运行测试3.先使用最少的代码来让失败的测试先跑起来4.编写足够的代码以使测试通过5.重构编写完整的代码以提高效率6.基准测试TDD是测试驱动…

quick-cocos2d-x游戏开发【3】——display.newSprite创建向导

游戏嘛。没有图片没有图片可以称为你的游戏&#xff0c;所以&#xff0c;我们看一下使用quick如何创建精灵的方式。quick的api精灵族的创造仍然是非常具体的解释。因此&#xff0c;建立非常easy。display.newSprite(filename, x, y, params) filename&#xff1a;精灵文件名称 …

JSON http://www.cnblogs.com/haippy/archive/2012/05/20/2509329.html

js: JSON.stringify(idinfo)//将对象转化为 JSON串 //查询后为将json串赋值给表单 function _form1_load() { AOS.ajax({ url: getForm1Info.jhtml, ok: function (data) {//{cardno_5300129, sex_2, age_如花, name_凤} …

mysql update 并发 慢_MySQL跑在CentOS 6 和 7上的性能比较

点击蓝色“程序猿DD”关注我哟加个“星标”&#xff0c;不忘签到哦来源&#xff1a;yangyidba关注我&#xff0c;回复口令获取可获取独家整理的学习资料&#xff1a;- 001 &#xff1a;领取《Spring Boot基础教程》- 002 &#xff1a;领取《Spring Cloud基础教程》一 前言计划今…

远程控制virtual box虚拟机系统的三种方式

远程控制virtual box虚拟机系统的三种方式【阅读时间&#xff1a;5分钟】1.使用现有的远程控制软件2.使用SSH连接3.使用远程桌面控制虚拟机系统对于把虚拟机安装在寝室笔记本的人来说&#xff0c;能够远程控制虚拟机的系统是很重要的一件事&#xff0c;而远程控制虚拟机的方式一…

Kernel那些事儿之内存管理(7) --- Slab(上)

前面讲的buddy system算法&#xff0c;分配内存的最小单位是一个页面&#xff08;例如 4K&#xff09;。这对于大的内存申请比较适用。可是实际生活中&#xff0c;Kernel经常需要分配小的内存空间&#xff0c;比如几十个字节&#xff0c;这个时候怎么办呢&#xff1f;不同的人可…

Vyond制作2D动画学习教程

Vyond为2D动画提供了极其简单的分解视频创建过程。 你会学到什么 课程获取&#xff1a;Vyond制作2D动画学习教程-云桥网 您将学习如何为2d动画制作画外音 您将学习如何使用Vyond轻松创建精彩的动画视频 流派:电子学习| MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xf…

Blender3.0电影级别CG场景制作视频教程

Blender 3.0的电影场景制作–8小时以上的主教程 三本教程合三为一 你会学到什么 你将学习如何在Blender中建模 你将学习如何在Blender中创建更复杂的纹理 你将学习如何创建一个场景&#xff0c;设置摄像机和灯光 你将在Blender中学习动画的基础知识 你将会学到如何在Blender中…

Android WebView使用与JavaScript使用

WebView基本使用 WebView是View的一个子类&#xff0c;可以让你在activity中显示网页。 可以在布局文件中写入WebView&#xff1a;比如下面这个写了一个填满整个屏幕的WebView&#xff1a; <?xml version"1.0" encoding"utf-8"?> <WebView x…

YOLOv8-Detect训练CoCo数据集+自己的数据集

至此,整个训练预测阶段完成。此过程同样可以在linux系统上进行,在数据准备过程中需要仔细,保证最后得到的数据准确,最好是用显卡进行训练。有问题评论区见!

lvs服务器需要开启web服务么_Nginx+Keepalived实现web服务器高可用

1、Nginx业务背景现公司需求快速搭建web服务器&#xff0c;对外提供给用户web服务。需求拆分需要基于http协议的软件&#xff0c;搭建服务实现介绍常见用法&#xff1a;1) web服务器软件 httpd http协议同类的web服务器软件&#xff1a;apache(老牌) nginx(俄罗斯) IIS(微软)2)…

centos使用镜像源轻松配置golang+vscode的方法

Title&#xff1a;centos使用镜像源轻松配置golangvscode的方法 &#xff08;阅读时间&#xff1a;约5分钟&#xff09; 零.序言 最近笔者在上一门名为服务计算的课程&#xff0c;在老师的作业博客中提到&#xff0c;安装golangvscode环境总会遇到各种网络问题&#xff0c;在…

MySQL_update同一张表

update tb1 inner join(select type, count(*) as cntfrom tb1 group by type)as der using(type)set tb1.cnt der.cnt转载于:https://www.cnblogs.com/MarchThree/p/4641515.html

在SolidWorks 3D CAD中构建乐高直升机

以有趣而独特的方式练习您的3D CAD技能 你会学到什么 练习SolidWorks三维CAD的使用 学习如何使用机械伴侣 创建直升机的零件 将零件组装成工作模型 类型:电子教学| MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;48.0 KHz 语言&#xff1a;英语中英文字幕&#xf…

CSS局限属性contain:优化渲染性能的利器

在网页开发中,优化渲染性能是一个重要的目标。CSS局限属性contain是一个强大的工具,可以帮助我们提高网页的渲染性能。本文将介绍contain属性的基本概念、用法和优势,以及如何使用它来优化网页的渲染过程。

利用java多线程向MongoDB中批量插入静态文件

第一步、开发环境&#xff1a; win7 64位(注&#xff1a;MongoDb在32位windows上有数量限制(2G)&#xff0c;详见官方文档) Mongodb3.2 mongofb_java_driver 3.2.2 第二部、安装mongodb,并开启服务 略&#xff1a;可参见官方文档 第三部、代码 import java.io.BufferedReader; …

为啥我从后台查到的值在页面显示的是undefined_再谈一个管理后台列表功能应有的素质...

​大家能看到的这个号第1篇文章《无心朝政&#xff0c;列表功能分析下》就是讲列表功能。虽然当时写的时候特别认真&#xff0c;但基本是围绕“列表功能”这个广泛的词来阐述的。最近在做一个体育赛事赛程的后台管理系统 Match-Schedule&#xff0c;对管理后台列表有更多的体会…

Go语言的错误异常处理机制及其应用

一、背景 在日常编写golang程序或阅读别人的golang代码时&#xff0c;我们总会看到如下的一堆代码块&#xff1a; xx, err func(xx) if err ! nil {//do sth. to tackle this problem }这种经典的显式错误处理方式&#xff0c;在golang开发中几乎无处不在&#xff0c;了解过…

【Win10 应用开发】语音命令与App Service集成

昨天&#xff0c;老周演示了语音命令集成这一高大上功能&#xff0c;今天咱们来点更高级的语音命令。 在昨天的例子中&#xff0c;响应语音命令是需要启动应用程序的&#xff0c;那么如果可以不启动应用程序&#xff0c;就直接在小娜面板上进行交互&#xff0c;是不是会更高大小…

Maya 2022中的硬表面建模技术学习视频教程

Maya 2022中的硬表面建模 信息: 使用正确的拓扑和边流在Maya中建模硬曲面对象。 你会学到什么 硬质表面工具和技术 细分工作流程 边缘流动控制 正确拓扑 材料设置 Studio Lightning 渲染 持续时间16小时30分钟 1280X720 MP4 大小解压后&#xff1a;11.5G 语言&#xff1a;英…

六年级小学python第四讲_python第四讲

列表的排序 升序&#xff1a;从小到大的排序 降序:从大到小的排序 示例&#xff1a; num_list [120,250,11,44,77,45,22,390] num_list.sort() # 升序 - 从小到大 print(num_list) # 对列表本身做了修改 num_list.sort(reverseTrue)#降序 为False#升序 print(num_list) 反转 p…

android之AlertDialog 点击其它区域自己主动消失

遇到一个问题记录下来&#xff0c;在开发中使用了AlertDialog&#xff0c;想点击屏幕其它区域的时候让这个dialog消失&#xff0c;一開始不做不论什么设置&#xff0c;在小米手机能够正常显示&#xff0c;可是在三星中却有问题。后来发现少了一个属性&#xff1a; View dilaogV…

中级实训第一天的自学报告

目录【阅读时间&#xff1a;约10分钟】中级实训第一天的自学报告姓名&#xff1a;隐藏敏感信息 学号&#xff1a;隐藏敏感信息一、Vi/Vim二、Java三、Ant四、Junit【附加】五、SonarQube【附加】六、 编译运行BugRunner七、 总结中级实训第一天的自学报告 姓名&#xff1a;隐藏…

完整的Blender三维课程:素描到三维艺术的初学者

使用Blender创建3D艺术。初级课程 你会学到什么 使用Blender并理解它的界面 创建3D模型 创建您自己的材料 布料仿真、纹理和雕刻 第三种解释的相机法则 照相机景深 灯光设置 渲染 如何使用参考素材进行3D素描和建模&#xff1f;参考镜头也包括在内。 课程中包含所有章节场景文…

VirtualBox: Effective UID is not root

为什么80%的码农都做不了架构师&#xff1f;>>> 桌面上运行virtualbox出错: The virtual machine xp has terminated unexpectedly during startup with exit code 1 (0x1). Effective UID is not root(euid1000 egid482 uid1000 gid482)(rc-10) Please try reinst…

ironpython 教程_「ironpython」VS2017 IronPython做界面

本人开始做毕设了&#xff0c;但老师说工具要有界面&#xff0c;所以就开始找Python做界面的东西……之前做过C#的界面&#xff0c;脱拉拽很快界面就完成了&#xff0c;后来我查了下IronPython是用C#写的python解释器&#xff0c;也可以脱拉拽做界面&#xff0c;于是就开始尝试…

4、jQuery实现的全选、反选和不选功能

2019独角兽企业重金招聘Python工程师标准>>> 这个地址更权威&#xff1a;最好的选择&#xff1a;http://www.sucaihuo.com/js/10.html <html><head><title>TODO supply a title</title><meta charset"UTF-8"><meta name…

构建自己的PHP框架--构建缓存组件(1)

作为一个框架&#xff0c;我们还没有相应的缓存组件&#xff0c;下面我们就来构建我们的缓存组件。 先来定义一下接口&#xff0c;在 src 文件夹下创建 cache 文件夹&#xff0c;在cache文件夹下创建 CacheInterface.php 文件&#xff0c;其中定义 Cache 相应的接口&#xff0c…

基于Golang的CLI 命令行程序开发

基于Golang的CLI 命令行程序开发 【阅读时间&#xff1a;约15分钟】一. CLI 命令行程序概述二. 系统环境&项目介绍&开发准备1.系统环境2.项目介绍3.开发准备三.具体程序设计及Golang代码实现1.selpg的程序结构2.导入的库3.sp_args结构体4.全局变量4.main函数5.process_…