设计模式(十四)Chain of Responsibility模式
Chain of Responsibility模式就是当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任。也就是说,当一个人被要求做什么事时,如果他可以做就自己做,如果不能做就转给下一个人,以此类推。
下面是示例程序的类图。

下面是示例程序代码。
package bigjunoba.bjtu.handler;
public class Trouble {
private int number;
public Trouble(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
public String toString() {
return "[Trouble " + number + "]";
}
}
Trouble类是表示发生的问题的类,number作为问题编号,通过getNumber方法得到问题编号。
package bigjunoba.bjtu.handler;
public abstract class Support {
private String name;
private Support next;
public Support(String name) {
super();
this.name = name;
}
public Support setNext(Support next) {
this.next = next;
return next;
}
public final void support(Trouble trouble) {
if (resolve(trouble)) {
done(trouble);
} else if (next != null) {
next.support(trouble);
}else {
fail(trouble);
}
}
public String toString() {
return "[" + name + "]";
}
protected abstract boolean resolve(Trouble trouble);
protected void done(Trouble trouble) {
System.out.println(trouble + " is resolved by " + this + "." );
}
protected void fail(Trouble trouble) {
System.out.println(trouble + " cannot be resolved.");
}
}
Support类是用来解决问题的抽象类,它是职责链上的对象。next字段保存了要推卸给的对象,即Support类的实例,可以通过setNext方法设定该对象。resolve方法如果返回true,则表示问题已经被处理,如果返回false,则表示问题还没有被处理。support方法调用resolve方法,如果解决了问题,那么就调用done方法,如果否则将问题交给下一个对象,如果到最后一个对象仍然没有人处理,那么就调用fail方法。这里注意的是support方法调用抽象resolve方法,这属于Template Method模式。
package bigjunoba.bjtu.concretehandler; import bigjunoba.bjtu.handler.Support;
import bigjunoba.bjtu.handler.Trouble; public class NoSupport extends Support{ public NoSupport(String name) {
super(name);
} @Override
protected boolean resolve(Trouble trouble) {
return false;
} }
package bigjunoba.bjtu.concretehandler; import bigjunoba.bjtu.handler.Support;
import bigjunoba.bjtu.handler.Trouble; public class OddSupport extends Support { public OddSupport(String name) {
super(name);
} @Override
protected boolean resolve(Trouble trouble) {
if (trouble.getNumber() % 2 == 1) {
return true;
} else {
return false;
}
} }
package bigjunoba.bjtu.concretehandler; import bigjunoba.bjtu.handler.Support;
import bigjunoba.bjtu.handler.Trouble; public class SpecilaSupport extends Support{ private int number; public SpecilaSupport(String name, int number) {
super(name);
this.number = number;
} @Override
protected boolean resolve(Trouble trouble) {
if (trouble.getNumber() == number) {
return true;
} else {
return false;
}
}
}
package bigjunoba.bjtu.concretehandler; import bigjunoba.bjtu.handler.Support;
import bigjunoba.bjtu.handler.Trouble; public class LimitSupport extends Support{ private int limit; public LimitSupport(String name, int limit) {
super(name);
this.limit = limit;
} @Override
protected boolean resolve(Trouble trouble) {
if (trouble.getNumber() < limit) {
return true;
} else {
return false;
}
} }
这四种类Support类的子类不难理解。NoSupport类永远不解决问题;LimitSupport类只解决编号小于limit值的问题;OddSupport类只解决奇数编号问题;SpecialSupport类只解决特定编号的问题。
package bigjunoba.bjtu.test; import bigjunoba.bjtu.concretehandler.LimitSupport;
import bigjunoba.bjtu.concretehandler.NoSupport;
import bigjunoba.bjtu.concretehandler.OddSupport;
import bigjunoba.bjtu.concretehandler.SpecilaSupport;
import bigjunoba.bjtu.handler.Support;
import bigjunoba.bjtu.handler.Trouble; public class Main { public static void main(String[] args) {
Support lian1 = new NoSupport("LianOne");
Support lian2 = new LimitSupport("LianTwo", 100);
Support lian3 = new SpecilaSupport("LianThree", 429);
Support lian4 = new LimitSupport("LianFour", 200);
Support lian5 = new OddSupport("LianFive");
Support lian6 = new LimitSupport("LianSix", 300);
//形成职责链
lian1.setNext(lian2).setNext(lian3).setNext(lian4).setNext(lian5).setNext(lian6);
//制造各种问题
for (int i = 0; i < 500; i += 33) {
lian1.support(new Trouble(i));
}
} }
Main类首先生成了6个解决问题的实例,虽然都是Support类型的,但实际上由于Support类是抽象类,因此这些实例分别是四个不同的子类的实例。然后形成了职责链,接着制造问题进行处理。
[Trouble 0] is resolved by [LianTwo].
[Trouble 33] is resolved by [LianTwo].
[Trouble 66] is resolved by [LianTwo].
[Trouble 99] is resolved by [LianTwo].
[Trouble 132] is resolved by [LianFour].
[Trouble 165] is resolved by [LianFour].
[Trouble 198] is resolved by [LianFour].
[Trouble 231] is resolved by [LianFive].
[Trouble 264] is resolved by [LianSix].
[Trouble 297] is resolved by [LianFive].
[Trouble 330] cannot be resolved.
[Trouble 363] is resolved by [LianFive].
[Trouble 396] cannot be resolved.
[Trouble 429] is resolved by [LianThree].
[Trouble 462] cannot be resolved.
[Trouble 495] is resolved by [LianFive].
根据输出结果来举一个例子具体分析一下这个过程。假设问题编号是429,那么可以这样来分析,首先创建了一个Trouble实例,并且把问题编号number设置为429,然后这个429问题实例传递给support方法,并用lian1来调用这个方法。主要分析的是调用方法的过程:先调用NoSupport类的resolve方法,结果返回false,然后next字段保存的是lian2,不为空,因此要执行lian2的support方法...以此类推,最后发现lian1,2都解决不了,最后交给了3,3可以解决,程序结束。这里的思想是用到了递归。
有一个时序图也可以用来帮助理解。

下面是Chain of Responsibility模式的类图。

这里对类图不做过多解释,通过示例程序对这一模式理解应该很到位。
设计模式(十四)Chain of Responsibility模式的更多相关文章
- 设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型)
设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型) 1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的 ...
- Java设计模式(14)责任链模式(Chain of Responsibility模式)
Chain of Responsibility定义:Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合, ...
- 设计模式19:Chain Of Responsibility 职责链模式(行为型模式)
Chain Of Responsibility 职责链模式(行为型模式) 请求的发送者与接受者 某些对象请求的接受者可能有多种多样,变化无常…… 动机(Motivation) 在软件构建过程中,一个请 ...
- 《图解设计模式》读书笔记6-2 Chain of Responsibility模式
目录 1. 简介 2. 示例程序 类图 代码 3. 模式的角色和类图 角色 类图 4. 思路拓展 1. 简介 Chain of Responsibility模式是责任链模式,模式的核心就是转移责任.就 ...
- java设计模式解析(11) Chain责任链模式
设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析(4) ...
- Chain of Responsibility模式
熟悉VC/MFC的都知道,VC是“基于消息,事件驱动”,消息在VC开发中起着举足轻重的作用.MFC提供了消息的处理的链式处理策略,处理消息的请求将沿着预定好的路径依次进行处理.消息的发送者并不知道该消 ...
- 设计模式(二十四)——职责链模式(SpringMVC源码分析)
1 学校 OA 系统的采购审批项目:需求是 采购员采购教学器材 1) 如果金额 小于等于 5000, 由教学主任审批 (0<=x<=5000) 2) 如果金额 小于等于 10000, ...
- 设计模式学习笔记(十四)责任链模式实现以及在Filter中的应用
责任链模式(Chain Of Responsibility Design Pattern),也叫做职责链,是将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求.当有请求发生时,可将请求沿着这条 ...
- 职责链(Chain of Responsibility)模式在航空货运中的运用实例
设计模式这东西,基本上属于“看懂一瞬间,用会好几年”.只有实际开发中,当某一模式很好的满足了业务需求时,才会有真切的感觉.借用一句<闪电侠>中,绿箭侠教导闪电侠的台词:“不是你碰巧遇到了它 ...
随机推荐
- Scala Class etc.
Classes 一个源文件可包含多个类,每个类默认都是 public 类字段必须初始化,编译后默认是 private,自动生成 public 的 getter/setter :Person 示例 pr ...
- 更该clover软件图标(任务栏显示)
1.首先介绍一个Clover软件,Clover 的功能就是给资源管理器加上 Chrome 一样的标签页,像下面这样,你会爱上它的效率,和浏览器一样的操作方式. 2.它自带的系统图标比较丑(虽然作者说挺 ...
- WebGL简易教程(九):综合实例:地形的绘制
目录 1. 概述 2. 实例 2.1. TerrainViewer.html 2.2. TerrainViewer.js 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL简易教程(八 ...
- ueditor的初始化赋值
ue.ready(function () {ue.setContent('初始内容'); //赋值给UEditor });
- Linux Shell 基础知识(二)
1.本文知识结构 2.文件的查询与检索 2.1. cd 目录切换 找到文件/目录位置:cd 切换到上一个工作目录: cd - 切换到home目录: cd or cd ~ 显示当前路径: pwd 更改当 ...
- 文件操作——RandomAccessFile
文件操作——RandomAccessFile 构建RandomAccessFileJava提供了一个可以对文件随机访问的操作,访问包括读和写操作.该类名为RandomAccessFile.该类的读 ...
- springboot与docker整合
一.springboot与docker整合 a.创建Dockerfile FROM java MAINTAINER "Wing"<1561815137@qq.com> ...
- 什么是ECMAScript、什么又是ECMA?
转载:针对于ECMA5Script .ECMAScript6.TypeScript的认识 什么是ECMAScript.什么又是ECMA? Ecma国际(Ecma International)是一家国际 ...
- 做高逼格程序员之说走就走的「Windows」
简介:随着移动固态硬盘越来越便宜,网上逐渐出来一个黑科技.Windows To GO见名知意.简单来说就是在U盘或者是移动固态硬盘上安装Windows系统.达到即插即用. WTG 简介 Windows ...
- ui自动化测试
一.梳理 1.根据要求需要自动添加很多条数据 2.这就涉及到ui方面的知识.元素定位的方法(这个就能遇到很多坑,要完全掌握元素定位才能避免进坑).循环等(代码基础要掌握好) 二.操作 选择进行自动化操 ...