职责链模式(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;
  11. }
  1. // 抽象请求类
  2. abstract class AbstractRequest {
  3. private String content = null;
  4. public AbstractRequest(String content) {
  5. this.content = content;
  6. }
  7. public String getContent() {
  8. return this.content;
  9. }
  10. // 获得请求的级别
  11. public abstract int getRequestLevel();
  12. }
  1. // 具体请求类01
  2. class Request01 extends AbstractRequest {
  3. public Request01(String content) {
  4. super(content);
  5. }
  6. @Override
  7. public int getRequestLevel() {
  8. return Levels.LEVEL_01;
  9. }
  10. }
  11. // 具体请求类02
  12. class Request02 extends AbstractRequest {
  13. public Request02(String content) {
  14. super(content);
  15. }
  16. @Override
  17. public int getRequestLevel() {
  18. return Levels.LEVEL_02;
  19. }
  20. }
  21. // 具体请求类03
  22. class Request03 extends AbstractRequest {
  23. public Request03(String content) {
  24. super(content);
  25. }
  26. @Override
  27. public int getRequestLevel() {
  28. return Levels.LEVEL_03;
  29. }
  30. }
  1. // 抽象处理者类,
  2. abstract class AbstractHandler {
  3. // 责任链的下一个节点,即处理者
  4. private AbstractHandler nextHandler = null;
  5. // 捕获具体请求并进行处理,或是将请求传递到责任链的下一级别
  6. public final void handleRequest(AbstractRequest request) {
  7. // 若该请求与当前处理者的级别层次相对应,则由自己进行处理
  8. if (this.getHandlerLevel() == request.getRequestLevel()) {
  9. this.handle(request);  
  10. } else {
  11. // 当前处理者不能胜任,则传递至职责链的下一节点
  12. if (this.nextHandler != null) {
  13. System.out.println("当前 处理者-0" + this.getHandlerLevel()
  14. + " 不足以处理 请求-0" + request.getRequestLevel());
  15. // 这里使用了递归调用
  16. this.nextHandler.handleRequest(request);  
  17. } else {
  18. System.out.println("职责链上的所有处理者都不能胜任该请求...");
  19. }
  20. }
  21. }
  22. // 设置责任链中的下一个处理者
  23. public void setNextHandler(AbstractHandler nextHandler) {
  24. this.nextHandler = nextHandler;
  25. }
  26. // 获取当前处理者的级别
  27. protected abstract int getHandlerLevel();
  28. // 定义链中每个处理者具体的处理方式
  29. protected abstract void handle(AbstractRequest request);
  30. }
  1. // 具体处理者-01
  2. class Handler01 extends AbstractHandler {
  3. @Override
  4. protected int getHandlerLevel() {
  5. return Levels.LEVEL_01;
  6. }
  7. @Override
  8. protected void handle(AbstractRequest request) {
  9. System.out.println("处理者-01 处理 " + request.getContent() + "\n");
  10. }
  11. }
  12. // 具体处理者-02
  13. class Handler02 extends AbstractHandler {
  14. @Override
  15. protected int getHandlerLevel() {
  16. return Levels.LEVEL_02;
  17. }
  18. @Override
  19. protected void handle(AbstractRequest request) {
  20. System.out.println("处理者-02 处理 " + request.getContent()+ "\n");
  21. }
  22. }
  23. // 具体处理者-03
  24. class Handler03 extends AbstractHandler {
  25. @Override
  26. protected int getHandlerLevel() {
  27. return Levels.LEVEL_03;
  28. }
  29. @Override
  30. protected void handle(AbstractRequest request) {
  31. System.out.println("处理者-03 处理 " + request.getContent()+ "\n");
  32. }
  33. }
  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. handler01.setNextHandler(handler02);
  10. handler02.setNextHandler(handler03);
  11. // 创建请求并提交到指责链中进行处理
  12. AbstractRequest request01 = new Request01("请求-01");
  13. AbstractRequest request02 = new Request02("请求-02");
  14. AbstractRequest request03 = new Request03("请求-03");
  15. // 每次提交都是从链头开始遍历
  16. handler01.handleRequest(request01);
  17. handler01.handleRequest(request02);
  18. handler01.handleRequest(request03);
  19. }
  20. }

测试结果:

  1. 处理者-01 处理 请求-01
  2. 当前 处理者-01 不足以处理 请求-02
  3. 处理者-02 处理 请求-02
  4. 当前 处理者-01 不足以处理 请求-03
  5. 当前 处理者-02 不足以处理 请求-03
  6. 处理者-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() 方法中使用了递归,栈空间的大小也是个问题。

个人看法:

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

职责链模式(Chain of Responsibility)的Java实现的更多相关文章

  1. atitit.设计模式(1)--—职责链模式(chain of responsibility)最佳实践O7 日期转换

    atitit.设计模式(1)---职责链模式(chain of responsibility)最佳实践O7 日期转换 1. 需求:::日期转换 1 2. 可以选择的模式: 表格模式,责任链模式 1 3 ...

  2. 设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型)

     设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就 ...

  3. 职责链模式(Chain of Responsibility)(对象行为型)

    1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就推卸给另外个一个部门(对象).至于到底谁来解决这个问题呢?政府部门就是为了可以避免屁民的请求与 ...

  4. 责任链模式 职责链模式 Chain of Responsibility Pattern 行为型 设计模式(十七)

    责任链模式(Chain of Responsibility Pattern) 职责链模式 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系 将这些对象连接成一条链,并沿着这 ...

  5. 设计模式 ( 十二 ) 职责链模式(Chain of Responsibility)(对象行为)

     设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决.不能解决就 ...

  6. 设计模式之职责链模式(Chain of Responsibility)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  7. 行为型设计模式之职责链模式(Chain of Responsibility)

    结构 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 适用性 有多个的对象可以处理一个请求,哪个 ...

  8. 职责链模式(chain of responsibility)

    一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所 ...

  9. 重温设计模式(三)——职责链模式(chain of responsibility)

    一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所 ...

  10. 设计模式:职责链模式(Chain of Responsibility)

    去年参加校招要到长沙来,这个对于我来说不是特别喜欢(但又必须的来,谁叫咱不是985.211的娃呢),但是对于某些人来说就是福音了.大四还有课,而且学校抓的比较严,所以对于那些想翘课的人来说这个是最好不 ...

随机推荐

  1. Javascript几种跨域方式总结

    在客户端编程语言中如javascript,同源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法.只有当两个域具有相同的协议,相同的主机,相同的端口时,我们就认定 ...

  2. 从源码解析LinkedList集合

         上篇文章我们介绍了ArrayList类的基本的使用及其内部的一些方法的实现原理,但是这种集合类型虽然可以随机访问数据,但是如果需要删除中间的元素就需要移动一半的元素的位置,效率低下.并且它内 ...

  3. 【Java基础】反射机制

    反射 反射可以使我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码链接.反射允许我们在编写和执行时,使我们的代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类 ...

  4. nginx内置全局变量

    nginx内置全局变量 $args        请求中的参数; $binary_remote_addr        远程地址的二进制表示 $body_bytes_sent        已发送的消 ...

  5. 每日java基础知识(01)

    1.java语言的主要特点. 跨平台性:一个应用可以不经过修改,就直接在不同的平台上运行. 面向对象:java是面向对象的语言,可以使用对象封装事物的属性和行为,可以使用面向对象的思想进行分析设计,并 ...

  6. 极光开发者服务推出统计产品JAnalytics

    极光以提供更加全面的开发者服务为目标,利用极光推送的数据和网络优势结合更丰富的功能,推出了极光统计(英文:JAnalytics).至此,极光开发者服务更加丰富.完善了. 极光统计有独立的统计 SDK, ...

  7. Lightbox 图片展示插件

    html <a href="<?php echo RESOURCES_BASE_FOLDER;?>image/default_pic.jpg" target=&q ...

  8. Java 大数A+B

    public class Solution { public int length = 0; public Object[] numToArrays(int num) { List<Intege ...

  9. observe.js 源码 学习笔记

    /** * observejs --- By dnt http://kmdjs.github.io/ * Github: https://github.com/kmdjs/observejs * MI ...

  10. Source Map入门教程

    部署前端之前,开发者通常会对代码进行打包压缩,这样可以减少代码大小,从而有效提高访问速度.然而,压缩代码的报错信息是很难Debug的,因为它的行号和列号已经失真.这时就需要Source Map来还原真 ...