职责链模式(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. 一张图看懂 JS 的事件机制

    一.为什么 JavaScript 单线程 假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准? 为了避免复杂性, JS ...

  2. Qt入门之基础篇(三):掌握Qt4的静态编译基本方法

    转载载请注明出处:CN_Simo. 导语: 前两章都提到过“静态编译”(Static Compilation),在Windows下一次静态编译差不多需要长达三个小时才能完成,而且还非常容易由于各种原因 ...

  3. java.lang.ClassNotFoundException: org.apache.commons.logging.Log

    严重: A child container failed during startjava.util.concurrent.ExecutionException: org.apache.catalin ...

  4. [编织消息框架][设计协议]优化long,int转换

    理论部分 一个long占8byte,大多数应用业数值不超过int每次传输多4byte会很浪费 有没有什么办法可以压缩long或int呢? 答案是有的,原理好简单,如果数值不超过int.max_valu ...

  5. 【2017-03-09】SQL Server 数据库基础、四种约束

    一.数据库和内存的区别 数据库:一些存储在硬盘上的数据文件 内存:计算机临时存储的一些数据 二.常用数据库 .Net - SQL Server PHP - MySql Java - Oreacl 三. ...

  6. ER图是啥?

    文章转载自「开发者圆桌」一个关于开发者入门.进阶.踩坑的微信公众号 E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型.属性和联系的方法,用来描述现 ...

  7. 我在ubuntu桌面系统下进行WEB开发常用的软件

    公司电脑本来是win系统的,不知道怎么突然中毒了,由于比较讨厌杀毒软件,所以之前都被我卸载掉了,所以我干脆重装了一个ubuntu系统 1.IDE    vscode 各种插件,自带Git,markdo ...

  8. 1740: [Usaco2005 mar]Yogurt factory 奶酪工厂

    1740: [Usaco2005 mar]Yogurt factory 奶酪工厂 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 119  Solved:  ...

  9. image图片拉伸

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #1d9421 } p.p2 ...

  10. XML(20161113)

    XML: 可扩展标记语言 在页面之间传递数据使用的,专门为了数据传输而存在 载体 HTML:超文本标记语言 显示 XML写法: 标签:<标签名></标签名> 特点:1.必须要有 ...