一文搞懂Java设计模式之责任链模式

简述:

前端时间再看一些类库的源码,发现责任链模式的强大之处,尤其是和建造者模式的结合后强大的动态可扩展性更是牛逼的一塌糊涂。接下来赶紧了解一下吧!

我们先来了解一下什么是责任链模式:

职责链模式(Chain of Responsibility):使多个对象都有机会处理同一个请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

应用场景:

为完成同一个请求,如果存在多个请求处理器以及未知请求处理器个数或者请求处理器可动态配置的情况下,可以考虑使用责任链模式。如OKHttp的拦截器就是使用的责任链模式。

实例UML图:

实例执行流程图:

实例:

    1、实例场景

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

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

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

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

    2、实例代码

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

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

/**
 * 类描述:请假对象
 *
 * @author lzy
 */
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;
 }

 @Override
 public String toString() {
 return "Request [name=" + name + ", reason=" + reason + ", days="
  + days + ",customInfo=" + customInfo + ", groupLeaderInfo="
  + groupLeaderInfo + ", managerInfo=" + managerInfo
  + ", departmentHeaderInfo=" + departmentHeaderInfo + "]";
 }

}

接下来再定义“批准结果”对象Result:

/**
 * 类描述:结果对象
 *
 * @author lzy
 *
 */
public class Result {
 public boolean isRatify;
 public String info;

 public Result() {

 }

 public Result(boolean isRatify, String info) {
 super();
 this.isRatify = isRatify;
 this.info = info;
 }

 public boolean isRatify() {
 return isRatify;
 }

 public void setRatify(boolean isRatify) {
 this.isRatify = isRatify;
 }

 public String getReason() {
 return info;
 }

 public void setReason(String info) {
 this.info = info;
 }

 @Override
 public String toString() {
 return "Result [isRatify=" + isRatify + ", info=" + info + "]";
 }
}

②我们接下来再来定义一个接口,这个接口用于处理Request和获取请求结果Result。

/**
 * 接口描述:处理请求
 *
 * @author lzy
 *
 */
public interface Ratify {
 // 处理请求
 public Result deal(Chain chain);

 /**
 * 接口描述:对request和Result封装,用来转发
 */
 interface Chain {
 // 获取当前request
 Request 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进行下一步转发用的,那我们就具体实现一下:

/**
 * 类描述:实现Chain的真正的包装Request和转发功能
 *
 * @author lzy
 *
 */
public class RealChain implements 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;
 }

 /**
 * 方法描述:具体转发功能
 */
 @Override
 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;
 }

 /**
 * 方法描述:返回当前Request对象或者返回当前进行包装后的Request对象
 */
 @Override
 public Request request() {
 return request;
 }

}

④ 经过上面几步我们已经完成了责任链模式的核心功能,接下来我们定义几个相关责任对象:GroupLeader、Manager和DepartmentHeader,并让他们实现Ratify接口。

/**
 * 组长
 *
 * @author lzy
 *
 */
public class GroupLeader implements Ratify {

 @Override
 public 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:早去早回");
 }
}

/**
 * 经理
 *
 * @author lzy
 *
 */
public class Manager implements Ratify {

 @Override
 public Result deal(Chain chain) {
 Request request = chain.request();
 System.out.println("Manager=====>request:" + request.toString());
 if (request.days() > 3) {
 // 构建新的Request
 Request newRequest = new Request.Builder().newRequest(request)
  .setManagerInfo(request.name() + "每月的KPI考核还不错,可以批准")
  .build();
 return chain.proceed(newRequest);

 }
 return new Result(true, "Manager:早点把事情办完,项目离不开你");
 }

}

/**
 * 部门领导
 *
 * @author lzy
 *
 */
public class DepartmentHeader implements Ratify {

 @Override
 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:不要着急,把事情处理完再回来!");
 }

}

到此,责任链模式的一个Demo就算是完成了,但为了方便调用,我们在写一个该责任链模式的客户端工具类ChainOfResponsibilityClient 如下:

/**
 * 类描述:责任链模模式工具类
 *
 * @author lzy
 *
 */
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(this, arrayList, request, 0);
  return realChain.proceed(request);
 }

}

OK,我们测试一下见证奇迹吧:

/**
 * 类描述:责任链模式测试类
 *
 * @author lzy
 *
 */
public class Main {

 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());
 }
}

这个请求是张三请事假5天,按照我们的约定应该请求会到达部门领导手里,且他看到请求的样式为:“ [name=张三, reason=事假, days=5customInfo=null, groupLeaderInfo=张三平时表现不错,而且现在项目也不忙, managerInfo=张三每月的KPI考核还不错,可以批准, departmentHeaderInfo=null]”

我们看一下打印的日志:

GroupLeader=====>request:Request [name=张三, reason=事假, days=5customInfo=null, groupLeaderInfo=null, managerInfo=null, departmentHeaderInfo=null]
Manager=====>request:Request [name=张三, reason=事假, days=5customInfo=null, groupLeaderInfo=张三平时表现不错,而且现在项目也不忙, managerInfo=null, departmentHeaderInfo=null]
DepartmentHeader=====>request:Request [name=张三, reason=事假, days=5customInfo=null, groupLeaderInfo=张三平时表现不错,而且现在项目也不忙, managerInfo=张三每月的KPI考核还不错,可以批准, departmentHeaderInfo=null]
结果:Result [isRatify=true, info=DepartmentHeader:不要着急,把事情处理完再回来!]

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

/**
 * 类描述:自定义“责任人”
 *
 * @author lzy
 *
 */
public class CustomInterceptor implements Ratify {

 @Override
 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, "同意请假");
 }

}

然后在测试类Main.java中调用如下:

/**
 * 类描述:责任链模式测试类
 *
 * @author lzy
 *
 */
public class Main {

 public static void main(String[] args) {

  Request request = new Request.Builder().setName("张三").setDays(5)
   .setReason("事假").build();
  ChainOfResponsibilityClient client = new ChainOfResponsibilityClient();
  client.addRatifys(new CustomInterceptor());
  Result result = client.execute(request);

  System.out.println("结果:" + result.toString());
 }

}

OK,看一下日志:

哈哈,责任链模式功能之强大还要多用多体会呀!

到此这篇关于Java设计模式之责任链模式的文章就介绍到这了,更多相关Java设计模式之责任链模式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java设计模式之责任链模式

    设计者往往会用拦截器去代替动态代理,然后将拦截器的接口提供给开发者,从而简化开发者的开发难度,但是拦截器可能有多个.举个例子,一个程序员需要请假一周,如果把请假申请单看成一个对象,那么它需要经过项目经理.部门经理.人事等多个角色的审批,每个角色都有机会通过拦截这个申请单进行审批或者修改.这事就要考虑提供项目经理.部门经理和人事的处理逻辑,所以需要提供3个拦截器,二传递的则是请假申请单. 当一个对象在一条链上被多个拦截器处理(拦截器也可以选择不拦截处理它)时,我们把这样的设计模式成为责任链模式,它

  • 实例讲解Java的设计模式编程中责任链模式的运用

    定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 类型:行为类模式 类图: 首先来看一段代码: public void test(int i, Request request){ if(i==1){ Handler1.response(request); }else if(i == 2){ Handler2.response(request); }else if(i == 3){ Handler3

  • Java设计模式之责任链模式简介

    对于使用过宏的朋友应该知道,利用宏可以实现一个键绑定多个技能.例如如果排在前面的技能有CD,则跳过此技能,执行之后的技能.记得曾经玩DK,打怪的时候,就是用一个键,一直按就行了.在servlet里的doGet和doPost方法,我们一般都把doGet请求发动到doPost里来处理,这也是一种责任链的模式. 这里,有个宏,绑定了"冰血冷脉"和"寒冰箭"两个技能,程序实例如下所示: package responsibility; /** * DOC 技能接口,要绑定的技

  • Java设计模式之责任链模式(Chain of Responsibility模式)介绍

    Chain of Responsibility定义:Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合,唯一共同点是在他们之间传递request.也就是说,来了一个请求,A类先处理,如果没有处理,就传递到B类处理,如果没有处理,就传递到C类处理,就这样象一个链条(chain)一样传递下去. 如何使用责任链模式 虽然这一段是如何使用CoR,但是也是演示什么是CoR. 有一个Handler接口: 复制代码

  • JAVA设计模式之责任链模式详解

    在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任. 从击鼓传花谈起 击鼓传花是一种热闹而又紧张的饮酒游戏.在酒宴上宾客依次坐定位置,由一人击鼓,击鼓

  • Java设计模式编程中的责任链模式使用示例

    责任链模式:多个对象由其对象对应下家的引用连成一条链,请求在这个链上传递,直到 链上的某一个接收对象处理此请求.因为请求的客户端并不知道链上最终是谁来处理这个请求,使得系统可以在不影响客户端的情况下动态地重新组织和分配责任, 从而避免了请求发送者与请求处理者之间的耦合. 责任链械中涉及到三种角色: 1,抽象处理者角色 2,具体处理者角色 3,请求发送者 小例子:假设去买房子,买房子就需要砍价, 卖房的人职位不同,可以优惠的价格也不同,不同职位就可以形成一个处理请求的链.我们暂定: * 基层销售员

  • 设计模式之责任链模式_动力节点Java学院整理

    定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 类型:行为类模式 类图: 首先来看一段代码: public void test(int i, Request request){ if(i==1){ Handler1.response(request); }else if(i == 2){ Handler2.response(request); }else if(i == 3){ Handler3

  • Java经典设计模式之责任链模式原理与用法详解

    本文实例讲述了Java经典设计模式之责任链模式.分享给大家供大家参考,具体如下: 责任链模式:多个对象由其对象对应下家的引用连成一条链,请求在这个链上传递,直到链上的某一个接收对象处理此请求.因为请求的客户端并不知道链上最终是谁来处理这个请求,使得系统可以在不影响客户端的情况下动态地重新组织和分配责任,从而避免了请求发送者与请求处理者之间的耦合. 责任链械中涉及到三种角色: 1,抽象处理者角色 2,具体处理者角色 3,请求发送者 小例子:假设去买房子,买房子就需要砍价, 卖房的人职位不同,可以优

  • 23种设计模式(19)java责任链模式

    23种设计模式第十九篇:java责任链模式 定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 类型:行为类模式 类图: 首先来看一段代码: public void test(int i, Request request){ if(i==1){ Handler1.response(request); }else if(i == 2){ Handler2.response(request); }els

  • 一文搞懂Java设计模式之责任链模式

    简述: 前端时间再看一些类库的源码,发现责任链模式的强大之处,尤其是和建造者模式的结合后强大的动态可扩展性更是牛逼的一塌糊涂.接下来赶紧了解一下吧! 我们先来了解一下什么是责任链模式: 职责链模式(Chain of Responsibility):使多个对象都有机会处理同一个请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 应用场景: 为完成同一个请求,如果存在多个请求处理器以及未知请求处理器个数或者请求处理器可动态配置的

  • 一文搞懂Java并发AQS的共享锁模式

    目录 概述 自定义共享锁例子 核心原理机制 源码解析 成员变量 共享锁获取acquireShared(int) 共享释放releaseShared(int) 概述 这篇文章深入浅出理解Java并发AQS的独占锁模式讲解了AQS的独占锁实现原理,那么本篇文章在阐述AQS另外一个重要模式,共享锁模式,那什么是共享锁呢? 共享锁可以由多个线程同时获取, 比较典型的就是读锁,读操作并不会产生副作用,所以可以允许多个线程同时对数据进行读操作而不会有线程安全问题,jdk中的很多并发工具比如ReadWrite

  • Java设计模式之责任链模式的概念、实现以及netty中的责任链模式

    本文先介绍了责任链模式的概念及简单实现.再贴了netty中对责任链的实现.最后总结了一点点思考. 1.概念相关 1.1.概念 责任链模式为请求创建了一个接收者对象的链,每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,沿着这条链传递请求,直到有对象处理它为止. 1.2.解决了什么: 客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了. 1.3.场景: 1.有多个对象可以处理同一

  • Java 设计模式之责任链模式及异步责任链详解

    目录 一.定义 二.普通责任链模式 三.异步责任链模式 一.定义 责任链模式(Chain of Responsibility Pattern):避免将一个请求的发送者与接受者耦合在一起,让多个对象都有机会处理请求.将接受请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止. 在很多源码都有涉及,如Mybatis拦截器.Filter- 责任链模式属于行为型模式. 二.普通责任链模式 抽象处理类:AbstractProcessor /** * 抽象处理类 */ public

  • Java设计模式之责任链模式的示例详解

    目录 应用场景 实际代码案例 无模式情况下的代码 采用责任链模式优化代码 采用建造者+责任链模式优化代码 责任链模式优缺点 责任链模式是将链中的每一个节点看做是一个对象,每个节点处理的请求均不相同,且内部自动维护下一个节点对象,当一个请求从链式的首段发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求位置,属于行为模式. 这里需要注意的是每个节点都能对对象进行一定的处理(也可以不处理),处理完成之后节点再进行判断还要进行后续处理还是说传递给下一个节点. 应用场景 首先举一个日常

  • Java设计模式中责任链模式详解

    目录 1.责任链设计模式的定义 2.责任链设计模式的优点与不足 3.责任链设计模式的实现思路 4.责任链设计模式应用实例 5.责任链设计模式应用场景 编程是一门艺术,大批量的改动显然是非常丑陋的做法,用心的琢磨写的代码让它变的更美观. 在现实生活中,一个事件需要经过多个对象处理是很常见的场景.例如,采购审批流程.请假流程等.公司员工请假,可批假的领导有部门负责人.副总经理.总经理等,但每个领导能批准的天数不同,员工必须根据需要请假的天数去找不同的领导签名,也就是说员工必须记住每个领导的姓名.电话

  • java设计模式(实战)-责任链模式

    目录 一:模式说明 二:项目实战 三:源代码 一:模式说明 模式定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果(取自<设计模式之禅>). 翻译:Client对象调用一个处理者(类)的方法,可能有多个处理者(实现类),但是该对象只需要调用第一个处理者(类)即可,该模式会自动分配谁来处理这个请求:这

随机推荐