责任链模式

转载 2015年07月08日 11:25:37
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://haolloyin.blog.51cto.com/1177454/342166

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

适用场景:

1、有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;

2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;

3、处理一个请求的对象集合应被动态指定。

通用类图:

在大学里面当班干部,时常要向上级申请各方面的东西。譬如申请全班外出秋游,普通同学将申请表交给班长,班长签字之后交给辅导员,辅导员批准之后上交到主任办公室…就是这样,一个请求(这里是一份申请表)有时候需要经过好几个级别的处理者(这里是辅导员、主任)的审查才能够最终被确定可行与否。

在这里表现出来的是一个职责链,即不同的处理者对同一个请求可能担负着不同的处理方式、权限,但是我们希望这个请求必须到达最终拍板的处理者(否则秋游就没戏了)。这种关系就很适合使用职责链模式了。

类图结构如下:

 代码实现如下:

  1. // 全局变量,接口类型  
  2. /**  
  3.  * 使用Java中的interface定义全局变量,可根据具体需要在   
  4.  * 具体的包中使用静态导入相关的全局变量,语法如下:   
  5.  *  import static package01.package02.*;  
  6.  */ 
  7. interface Levels {  
  8.     public static final int LEVEL_01 = 1;  
  9.     public static final int LEVEL_02 = 2;  
  10.     public static final int LEVEL_03 = 3;  

 

  1. // 抽象请求类  
  2. abstract class AbstractRequest {  
  3.     private String content = null;  
  4.  
  5.     public AbstractRequest(String content) {  
  6.         this.content = content;  
  7.     }  
  8.  
  9.     public String getContent() {  
  10.         return this.content;  
  11.     }  
  12.  
  13.     // 获得请求的级别  
  14.     public abstract int getRequestLevel();  

 

  1. // 具体请求类01  
  2. class Request01 extends AbstractRequest {  
  3.     public Request01(String content) {  
  4.         super(content);  
  5.     }  
  6.  
  7.     @Override 
  8.     public int getRequestLevel() {  
  9.         return Levels.LEVEL_01;  
  10.     }  
  11. }  
  12.  
  13. // 具体请求类02  
  14. class Request02 extends AbstractRequest {  
  15.     public Request02(String content) {  
  16.         super(content);  
  17.     }  
  18.  
  19.     @Override 
  20.     public int getRequestLevel() {  
  21.         return Levels.LEVEL_02;  
  22.     }  
  23. }  
  24.  
  25. // 具体请求类03  
  26. class Request03 extends AbstractRequest {  
  27.     public Request03(String content) {  
  28.         super(content);  
  29.     }  
  30.  
  31.     @Override 
  32.     public int getRequestLevel() {  
  33.         return Levels.LEVEL_03;  
  34.     }  

 

  1. // 抽象处理者类,  
  2. abstract class AbstractHandler {  
  3.     // 责任链的下一个节点,即处理者  
  4.     private AbstractHandler nextHandler = null;  
  5.  
  6.     // 捕获具体请求并进行处理,或是将请求传递到责任链的下一级别  
  7.     public final void handleRequest(AbstractRequest request) {  
  8.  
  9.         // 若该请求与当前处理者的级别层次相对应,则由自己进行处理  
  10.         if (this.getHandlerLevel() == request.getRequestLevel()) {  
  11.             this.handle(request);  
  12.         } else {  
  13.             // 当前处理者不能胜任,则传递至职责链的下一节点  
  14.             if (this.nextHandler != null) {  
  15.                 System.out.println("当前 处理者-0" + this.getHandlerLevel()  
  16.                         + " 不足以处理 请求-0" + request.getRequestLevel());  
  17.                   
  18.                 // 这里使用了递归调用  
  19.                 this.nextHandler.handleRequest(request);  
  20.             } else {  
  21.                 System.out.println("职责链上的所有处理者都不能胜任该请求...");  
  22.             }  
  23.         }  
  24.     }  
  25.  
  26.     // 设置责任链中的下一个处理者  
  27.     public void setNextHandler(AbstractHandler nextHandler) {  
  28.         this.nextHandler = nextHandler;  
  29.     }  
  30.  
  31.     // 获取当前处理者的级别  
  32.     protected abstract int getHandlerLevel();  
  33.  
  34.     // 定义链中每个处理者具体的处理方式  
  35.     protected abstract void handle(AbstractRequest request);  

 

  1. // 具体处理者-01  
  2. class Handler01 extends AbstractHandler {  
  3.     @Override 
  4.     protected int getHandlerLevel() {  
  5.         return Levels.LEVEL_01;  
  6.     }  
  7.  
  8.     @Override 
  9.     protected void handle(AbstractRequest request) {  
  10.         System.out.println("处理者-01 处理 " + request.getContent() + "\n");  
  11.     }  
  12. }  
  13.  
  14. // 具体处理者-02  
  15. class Handler02 extends AbstractHandler {  
  16.     @Override 
  17.     protected int getHandlerLevel() {  
  18.         return Levels.LEVEL_02;  
  19.     }  
  20.  
  21.     @Override 
  22.     protected void handle(AbstractRequest request) {  
  23.         System.out.println("处理者-02 处理 " + request.getContent()+ "\n");  
  24.     }  
  25. }  
  26.  
  27. // 具体处理者-03  
  28. class Handler03 extends AbstractHandler {  
  29.     @Override 
  30.     protected int getHandlerLevel() {  
  31.         return Levels.LEVEL_03;  
  32.     }  
  33.  
  34.     @Override 
  35.     protected void handle(AbstractRequest request) {  
  36.         System.out.println("处理者-03 处理 " + request.getContent()+ "\n");  
  37.     }  

 

  1. // 测试类  
  2. public class Client {  
  3.     public static void main(String[] args) {  
  4.         // 创建指责链的所有节点  
  5.         AbstractHandler handler01 = new Handler01();  
  6.         AbstractHandler handler02 = new Handler02();  
  7.         AbstractHandler handler03 = new Handler03();  
  8.  
  9.         // 进行链的组装,即头尾相连,一层套一层  
  10.         handler01.setNextHandler(handler02);  
  11.         handler02.setNextHandler(handler03);  
  12.  
  13.         // 创建请求并提交到指责链中进行处理  
  14.         AbstractRequest request01 = new Request01("请求-01");  
  15.         AbstractRequest request02 = new Request02("请求-02");  
  16.         AbstractRequest request03 = new Request03("请求-03");  
  17.           
  18.         // 每次提交都是从链头开始遍历  
  19.         handler01.handleRequest(request01);  
  20.         handler01.handleRequest(request02);  
  21.         handler01.handleRequest(request03);  
  22.     }  

测试结果:

  1. 处理者-01 处理 请求-01 
  2.  
  3. 当前 处理者-01 不足以处理 请求-02 
  4. 处理者-02 处理 请求-02 
  5.  
  6. 当前 处理者-01 不足以处理 请求-03 
  7. 当前 处理者-02 不足以处理 请求-03 
  8. 处理者-03 处理 请求-03 
在上面抽象处理者 AbstractHandler 类的 handleRequest() 方法中,被 protected 修饰,并且该方法中调用了两个必须被子类覆盖实现的抽象方法,这里是使用了模板方法模式(Template Mehtod)。其实在这里,抽象父类的 handleRequest() 具备了请求传递的功能,即对某些请求不能处理时,马上提交到下一结点(处理者)中,而每个具体的处理者仅仅完成了具体的处理逻辑,其他的都不用理。
 
记得第一次看到职责链模式的时候,我很惊讶于它能够把我们平时在代码中的 if..else.. 的语句块变成这样灵活、适应变化。例如:如果现在辅导员请长假了,但我们的秋游还是要争取申请成功呀,那么我们在 Client 类中可以不要创建 handler02,即不要将该处理者组装到职责链中。这样子处理比 if..else..好多了。或者说,突然来了个爱管闲事的领导,那么我照样可以将其组装到职责链中。
 
关于上面使用场景中提到的3个点:
1、处理者在运行时动态确定其实是我们在 Client 中组装的链所引起的,因为具体的职责逻辑就在链中一一对应起来;
2、因为不确定请求的具体处理者是谁,所以我们把所有可能的处理者组装成一条链,在遍历的过程中就相当于向每个处理者都提交了这个请求,等待其审查。并且在审查过程中,即使不是最终处理者,也可以进行一些请求的“包装”操作(这种功能类似于装饰者模式),例如上面例子中的签名批准;
3、处理者集合的动态指定跟上面的第1、2点类似,即在 Client 类中创建了所有可能的处理者。
 
不足之处:

1、对于每一个请求都需要遍历职责链,性能是个问题;

2、抽象处理者 AbstractHandler 类中的 handleRequest() 方法中使用了递归,栈空间的大小也是个问题。

 个人看法:

职责链模式对于请求的处理是不知道最终处理者是谁,所以是运行动态寻找并指定;而命令模式中对于命令的处理时在创建命令是已经显式或隐式绑定了接收者。

相关文章:

命令模式(Command)的两种不同实现(http://haolloyin.blog.51cto.com/1177454/339076

(Template Method)模板方法模式的Java实现(http://haolloyin.blog.51cto.com/1177454/333063

装饰模式(Decorator)与动态代理的强强联合(http://haolloyin.blog.51cto.com/1177454/338671

本文出自 “蚂蚁” 博客,请务必保留此出处http://haolloyin.blog.51cto.com/1177454/342166

职责链模式(C语言实现)

一. 概述 职责链模式: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 二. ...
  • HMSIWTV
  • HMSIWTV
  • 2014年09月27日 18:37
  • 1349

Java模式开发之责任链模式

从击鼓传花谈起  击鼓传花是一种热闹而又紧张的饮酒游戏。在酒宴上宾客依次坐定位置,由一人击鼓,击鼓的地方与传花的地方是分开的,以示公正。开始击鼓时,花束就开始依次传递,鼓声一落,如果花束在某人手中,则...
  • lizl
  • lizl
  • 2005年07月26日 14:34
  • 7430

从Tomcat中学习责任链模式

通过对Tomcat8.5.5版本的源码进行学习,发现Tomcat中有2个地方用到了责任链模式,一个是管道中的阀门,另一个是过滤器链中的过滤器。下面我们分别来看一下这两个责任链模式具体是如何使用的。首先...
  • jb_peng
  • jb_peng
  • 2016年10月21日 14:24
  • 709

《设计模式 ● 责任链》之业务场景

/************************************************************************************************** ...
  • webwalker
  • webwalker
  • 2012年03月21日 16:29
  • 4613

责任链模式综述(基础篇)

本篇综述责任链模式的提出动机、原理结构、典型实现和应用场景,并结合实例展现了其灵活性和可插拔性。首先,结合生活中“打扑克”的例子引出了责任链模式动机和应用场景,然后我们概述了责任链模式的内涵和结构,即...
  • justloveyou_
  • justloveyou_
  • 2017年03月30日 16:28
  • 2546

IOS设计模式之责任链模式

转载:http://my.oschina.net/daguoshi/blog/495573 本篇文章参照Objective-C编程之道,iOS设计模式解析一书(Carlo Chung)而来的,参考了...
  • lcg910978041
  • lcg910978041
  • 2016年04月24日 14:56
  • 430

责任链模式的7种不同实现

引言责任链模式是经典的GoF 23种设计模式之一,也许你已经了解这种模式。不管你是否熟悉,建议读者在阅读本文之前,不妨先思考下面三个问题: 1. 如何用多种风格迥异的编程范式来实现责任链模式? ...
  • liuwenzhe2008
  • liuwenzhe2008
  • 2017年04月19日 13:32
  • 2277

iOS设计模式--责任链模式

原文地址:http://my.oschina.net/daguoshi/blog/495573?fromerr=9lqAJyi7 何为责任链模式?     责任链模式的主要思想...
  • huakaihualuo316
  • huakaihualuo316
  • 2015年12月11日 16:53
  • 409

Android进阶系列之源码分析事件分发责任链模式

翱翔于源码的海洋,痛并快乐着.... 什么是责任链模式? 责任链模式(Chain of Responsibility)的目标是使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系...
  • sw5131899
  • sw5131899
  • 2017年01月03日 14:52
  • 396

责任链模式进阶:与AOP思想的融合与应用

AOP的理念可以很容易抽象出横切关注点,基于AOP理念我们可以将责任链模式中各具体处理角色中共同逻辑抽象出来并将其模块化以便提高代码复用率和系统可维护性。Java Web中的过滤器和Struts2中的...
  • justloveyou_
  • justloveyou_
  • 2017年03月30日 18:15
  • 3129
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:责任链模式
举报原因:
原因补充:

(最多只允许输入30个字)