责任型模式是什么?

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

责任链模式示意图

责任链模式的要素

  • 请求发起者
  • 抽象请求发起者
  • 抽象请求处理者
  • 具体的请求处理者

实际例子(此后的例子为转载别人的博客)

1、实例场景

在公司内部员工请假一般情况是这样的:员工在OA系统中提交一封请假邮件,该邮件会自动转发到你的直接上级领导邮箱里,如果你的请假的情况特殊的话,该邮件也会转发到你上级的上级的邮箱,根据请假的情况天数多少,系统会自动转发相应的责任人的邮箱。我们就以这样一种场景为例完成一个责任链模式的代码。为了更清晰的描述这种场景我们规定如下:

① GroupLeader(组长 ):他能批准的假期为2天,如果请假天数超过2天就将请假邮件自动转发到组长和经理邮箱。

② Manager(经理):他能批准的假期为4天以内,如果请假天数大于4天将该邮件转发到自动转发到组长、经理和部门领导的邮箱。

③ DepartmentHeader(部门领导):他能批准的假期为7天以内,如果大于7天就只批准7天。

2、实例代码

我们清楚了上面的场景以后就开始定义模型:

①根据面向对象的思想我们得定义需要用到的对象。OK,为了更加清楚的说明“责任链模式的可扩展性”问题我这里采用了建造者模式(这个模式我现在还不理解)构造Request对象,“请假”对象Request如下:

package myDesignPatternsTest.responsibleModel;public class Request {private String name;private String reason;private int days;private String groupLeaderInfo;private String managerInfo;private String departmentHeaderInfo;private String customInfo;public Request(Builder builder) {super();this.name = builder.name;this.reason = builder.reason;this.days = builder.days;this.groupLeaderInfo = builder.groupLeaderInfo;this.managerInfo = builder.managerInfo;this.departmentHeaderInfo = builder.departmentHeaderInfo;this.customInfo = builder.customInfo;}public static class Builder {public String name;public String reason;public int days;public String groupLeaderInfo;public String managerInfo;public String departmentHeaderInfo;public String customInfo;public Builder() {}public Builder setName(String name) {this.name = name;return this;}public Builder setReason(String reason) {this.reason = reason;return this;}public Builder setDays(int days) {this.days = days;return this;}public Builder setGroupLeaderInfo(String groupLeaderInfo) {this.groupLeaderInfo = groupLeaderInfo;return this;}public Builder setManagerInfo(String managerInfo) {this.managerInfo = managerInfo;return this;}public Builder setDepartmentHeaderInfo(String departmentHeaderInfo) {this.departmentHeaderInfo = departmentHeaderInfo;return this;}public Builder setCustomInfo(String customInfo) {this.customInfo = customInfo;return this;}public Builder newRequest(Request request) {this.name = request.name;this.days = request.days;this.reason = request.reason;if (request.groupLeaderInfo != null&& !request.groupLeaderInfo.equals("")) {this.groupLeaderInfo = request.groupLeaderInfo;}if (request.managerInfo != null && !request.managerInfo.equals("")) {this.managerInfo = request.managerInfo;}if (request.departmentHeaderInfo != null&& !request.departmentHeaderInfo.equals("")) {this.departmentHeaderInfo = request.departmentHeaderInfo;}if (request.customInfo != null && !request.customInfo.equals("")) {this.customInfo = request.customInfo;}return this;}public Request build() {return new Request(this);}}public String name() {return name;}public String reason() {return reason;}public int days() {return days;}public String groupLeaderInfo() {return groupLeaderInfo;}public String managerInfo() {return managerInfo;}public String departmentHeaderInfo() {return departmentHeaderInfo;}public String customInfo() {return customInfo;}@Overridepublic String toString() {return "Request [name=" + name + ", reason=" + reason + ", days="+ days + ",customInfo=" + customInfo + ", groupLeaderInfo="+ groupLeaderInfo + ", managerInfo=" + managerInfo+ ", departmentHeaderInfo=" + departmentHeaderInfo + "]";}}
package myDesignPatternsTest.responsibleModel;/*** 处理结果*/
public class Result {public Boolean isRatify;public String  info;public Result(Boolean isRatify, String info) {this.isRatify = isRatify;this.info = info;}@Overridepublic String toString() {return "Result{" +"isRatify=" + isRatify +", info='" + info + '\'' +'}';}
}
package myDesignPatternsTest.responsibleModel;/*** 处理请求的接口*/
public interface Ratify {//处理请求public Result deal(Chain chain);interface  Chain{//获取当前请求Request Request();//转发请求Result proceed(Request request);}}

看到上面的接口,可能会有人迷惑:在接口Ratify中为什么又定义一个Chain接口呢?其实这个接口是单独定义还是内部接口没有太大关系,但是考虑到Chain接口与Ratify接口的关系为提高内聚性就定义为内部接口了。定义Ratify接口是为了处理Request那为什么还要定义Chain接口呢?这正是责任链接口的精髓之处:转发功能及可动态扩展“责任人”,这个接口中定义了两个方法一个是request()就是为了获取request,如果当前Ratify的实现类获取到request之后发现自己不能处理或者说自己只能处理部分请求,那么他将自己的那部分能处理的就处理掉,然后重新构建一个或者直接转发Request给下一个责任人。可能这点说的不容易理解,我举个例子,在Android与后台交互中如果使用了Http协议,当然我们可能使用各种Http框架如HttpClient、OKHttp等,我们只需要发送要请求的参数就直接等待结果了,这个过程中你可能并没有构建请求头,那么框架帮你把这部分工作给做了,它做的工程中如果使用了责任链模式的话,它肯定会将Request进行包装(也就是添加请求头)成新的Request,我们姑且加他为Request1,如果你又希望Http做本地缓存,那么Request1又会被转发到并且重新进一步包装为Request2。总之Chain这个接口就是起到对Request进行重新包装的并将包装后的Request进行下一步转发的作用。如果还不是很明白也没关系,本实例会演示这一功能机制。

③上面说Chain是用来对Request重新包装以及将包装后的Request进行下一步转发用的,那我们就具体实现一下:

package myDesignPatternsTest.responsibleModel;import java.util.List;public class RealChain implements Ratify.Chain {public Request request;public List<Ratify> ratifyList;public int index;/*** 构造方法** @param ratifyList*            Ratify接口的实现类集合* @param request*            具体的请求Request实例* @param index*            已经处理过该request的责任人数量*/public RealChain(List<Ratify> ratifyList, Request request, int index) {this.ratifyList = ratifyList;this.request = request;this.index = index;}/***  把请求传下去* @return*/public Request Request() {return request;}/*** 请求转发类* @param request* @return*/public Result proceed(Request request) {Result proceed=null;if (ratifyList.size() > index){RealChain realChain = new RealChain(ratifyList, request, index + 1);Ratify ratify = ratifyList.get(index);proceed = ratify.deal(realChain);}return proceed;}
}
package myDesignPatternsTest.responsibleModel;public class DepartmentHeader implements  Ratify {public Result deal(Chain chain) {Request request = chain.Request();System.out.println("DepartmentHeader=====>request:"+ request.toString());if (request.days() > 7) {return new Result(false, "你这个完全没必要");}return new Result(true, "DepartmentHeader:不要着急,把事情处理完再回来!");}}
package myDesignPatternsTest.responsibleModel;public class GroupLeader implements Ratify {@Overridepublic Result deal(Chain chain) {Request Request=chain.Request();System.out.println("GroupLeader=========>request:"+Request.toString());if (Request.days() > 1) {// 包装新的Request对象Request newRequest = new Request.Builder().newRequest(Request).setManagerInfo(Request.name() + "平时表现不错,而且现在项目也不忙").build();return chain.proceed(newRequest);}return new Result(true, "GroupLeader:早去早回");}
}
package myDesignPatternsTest.responsibleModel;public class Manager implements Ratify {@Overridepublic Result deal(Chain chain) {Request request = chain.Request();System.out.println("Manager=====>request:" + request.toString());if (request.days() > 3) {// 构建新的RequestRequest newRequest = new Request.Builder().newRequest(request).setManagerInfo(request.name() + "每月的KPI考核还不错,可以批准").build();return chain.proceed(newRequest);}return new Result(true, "Manager:早点把事情办完,项目离不开你");}}
package myDesignPatternsTest.responsibleModel;import java.util.ArrayList;/*** 责任链工具类*/
public class ChainOfResponsibilityClient {private ArrayList<Ratify> ratifies;public ChainOfResponsibilityClient() {ratifies = new ArrayList<Ratify>();}/*** 方法描述:为了展示“责任链模式”的真正的迷人之处(可扩展性),在这里构造该方法以便添加自定义的“责任人”** @param ratify*/public void addRatifys(Ratify ratify) {ratifies.add(ratify);}/*** 方法描述:执行请求** @param request* @return*/public Result execute(Request request) {ArrayList<Ratify> arrayList = new ArrayList<Ratify>();arrayList.addAll(ratifies);arrayList.add(new GroupLeader());arrayList.add(new Manager());arrayList.add(new DepartmentHeader());RealChain realChain = new RealChain( arrayList, request, 0);return realChain.proceed(request);}}
package myDesignPatternsTest.responsibleModel;public class Client {public static void main(String[] args) {Request request = new Request.Builder().setName("张三").setDays(5).setReason("事假").build();ChainOfResponsibilityClient client = new ChainOfResponsibilityClient();Result result = client.execute(request);System.out.println("结果:" + result.toString());}
}

刚开始就提到这个责任链模式是可以“动态扩展的”,我们验证一下,首先自定义一个“责任人”(其实也可以叫拦截器):

package myDesignPatternsTest.responsibleModel;public class Custom implements  Ratify {public Result deal(Chain chain) {Request request = chain.Request();System.out.println("CustomInterceptor=>" + request.toString());String reason = request.reason();if (reason != null && reason.equals("事假")) {Request newRequest = new Request.Builder().newRequest(request).setCustomInfo(request.name() + "请的是事假,而且很着急,请领导重视一下").build();System.out.println("CustomInterceptor=>转发请求");return chain.proceed(newRequest);}return new Result(true, "同意请假");}}
package myDesignPatternsTest.responsibleModel;import java.util.ArrayList;/*** 责任链工具类*/
public class ChainOfResponsibilityClient {private ArrayList<Ratify> ratifies;public ChainOfResponsibilityClient() {ratifies = new ArrayList<Ratify>();}/*** 方法描述:为了展示“责任链模式”的真正的迷人之处(可扩展性),在这里构造该方法以便添加自定义的“责任人”** @param ratify*/public void addRatifys(Ratify ratify) {ratifies.add(ratify);}/*** 方法描述:执行请求** @param request* @return*/public Result execute(Request request) {ArrayList<Ratify> arrayList = new ArrayList<Ratify>();arrayList.addAll(ratifies);arrayList.add(new Custom());//新加的arrayList.add(new GroupLeader());arrayList.add(new Manager());arrayList.add(new DepartmentHeader());RealChain realChain = new RealChain( arrayList, request, 0);return realChain.proceed(request);}}
customInterceptor=>Request [name=张三, reason=事假, days=5,customInfo=null, groupLeaderInfo=null, managerInfo=null, departmentHeaderInfo=null]
CustomInterceptor=>转发请求
GroupLeader=========>request:Request [name=张三, reason=事假, days=5,customInfo=张三请的是事假,而且很着急,请领导重视一下, groupLeaderInfo=null, managerInfo=null, departmentHeaderInfo=null]
Manager=====>request:Request [name=张三, reason=事假, days=5,customInfo=张三请的是事假,而且很着急,请领导重视一下, groupLeaderInfo=null, managerInfo=张三平时表现不错,而且现在项目也不忙, departmentHeaderInfo=null]
DepartmentHeader=====>request:Request [name=张三, reason=事假, days=5,customInfo=张三请的是事假,而且很着急,请领导重视一下, groupLeaderInfo=null, managerInfo=张三每月的KPI考核还不错,可以批准, departmentHeaderInfo=null]
结果:Result{isRatify=true, info='DepartmentHeader:不要着急,把事情处理完再回来!'}

责任链模式适用的情况

  1. 系统中已经有一个由处理者组成的链,这个链可能由复合模式给出
  2. 当有多于一个的处理者对象处理一个请求,而且事先并不知道到底由哪一个处理者对象处理一个请求,这个处理者是动态决定的
  3. 当系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定是哪一个处理者对象会处理这个请求
  4. 当处理一个请求的处理者对象集合需要动态的指定时

这个模式不是特别理解,过段时间再来补充

设计模式-责任型模式(责任链模式)相关推荐

  1. 设计模式-行为型模式-责任链模式

    设计模式-行为型模式-责任链模式 定义 将请求沿着链传递,然后直到对象处理即可. UML图 代码 基本的责任链 public class Test{public void test(int i, Re ...

  2. 简易理解设计模式之:责任链模式——OA中请假流程示例

    介绍: 责任链模式属于行为型设计模式.它的定义为:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,只到有对象处理它为止. 类图: ...

  3. 设计模式 — 行为型模式 — 责任链模式

    目录 文章目录 目录 责任链模式 应用场景 代码示例 责任链模式 责任链模式,将多个处理方法连接成一条链条,请求将在这条链条上流动直到该链条中有一个节点可以处理该请求.通常这条链条是一个对象包含对另一 ...

  4. 《JAVA设计模式系列》责任链模式

    文章目录 责任链模式 责任链模式优缺点 应用场景 责任链模式的结构 实现流程 责任链模式 责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这 ...

  5. 《java设计模式》之责任链模式

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

  6. 设计模式-请假流程-责任链模式

    责任链模式的定义 ​ 首先我们可以先看一下责任链模式的定义: ​ Avoid coupling the sender of a request to its receiver by giving mo ...

  7. 设计模式(四)责任链模式——责任链模式结构

    定义 责任链是行为型设计模式的一种,通过前一个处理者记录下一个处理者的方式形成一条处理链.客户端在调用时只需要将请求传递到责任上即可,无需关注链路中的具体的传递过程.而链路中内部的处理,是按照前一个处 ...

  8. 设计模式探索之责任链模式

    责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计模式属于行为型模式. ...

  9. 【深入设计模式】责任链模式—责任链模式及责任链模式在源码中的应用

    文章目录 1. 责任链模式 1.1 责任链模式简介 1.2 责任链模式结构 1.3 责任链模式示例 2. 责任链模式在源码中的应用 2.1 Servlet 中的责任链模式 2.2 Spring 中的责 ...

  10. Java描述设计模式(15):责任链模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景描述 1.请假审批流程 公司常见的请假审批流程:请假天数 当 day<=3 天,项目经理审批 当 3<day<= ...

最新文章

  1. knllgobjinfo: MISSING Streams multi-version data dictionary!!! 的一次处理 (二)
  2. 图形界面终端下打印内核调试信息
  3. linux检查是否安装proc编译器,编译安装 GCC 4.9并验证使用
  4. LINUX下软件包的安装与使用
  5. java例7_在Java 7中处理周数
  6. python执行linux和window的命令
  7. ios 百度地图指定区域_获取百度地图可视区域范围的数据
  8. 前端学习(3321):瀑布流的方式演示
  9. android相关论文,android
  10. UE4 如何导入外部插件包
  11. 提高电商ROI的方法有哪些?
  12. TI - MCU - MSP430使用指南1 - MSP430简介及选型指南
  13. UA用Mode-Driven的使用笔记
  14. 屋里的大象:粒子物理学有自己的死神
  15. 软件测试基础知识大全【乐搏TestPRO】
  16. Spring之DI注入方式
  17. Tomcat是干嘛用的?企业级Tomcat部署实践及安全调优
  18. border-radius没有效果
  19. 父---->曾孙,跨多层组件传值方法provide/inject
  20. Connect to maven.google.com:443 [maven.google.com] failed: Connection timed out: connect 解决办法

热门文章

  1. 微信模板消息推送接口说明
  2. s7400plc运行时关闭服务器,S7-400PLC频繁死机
  3. 【企业微信开发】企业微信开发测试推送应用消息流程
  4. 征文投稿丨只需6步!轻量应用服务器快速建站指南
  5. html内联样式(表),外部样式表
  6. 英勇青铜5基金个人策略
  7. C语言 输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数
  8. android常用控件实验报告,ui设计实验报告.doc
  9. H.264里的SEI——自定义信息(SEI)
  10. 企业不得不知的BYOD实施十大风险