设计模式(十四)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)模式在航空货运中的运用实例
设计模式这东西,基本上属于“看懂一瞬间,用会好几年”.只有实际开发中,当某一模式很好的满足了业务需求时,才会有真切的感觉.借用一句<闪电侠>中,绿箭侠教导闪电侠的台词:“不是你碰巧遇到了它 ...
随机推荐
- SPSS学习笔记参数检验—单样本t检验
单样本t检验 目的:利用来自总体的样本数据,推断该总体的均值是否与指定的检验值存在差异. 适用条件:样本来自的总体应服从或者近似服从正态分布. 注:当样本量n比较大时:由中心极限定理得知,即使原数据不 ...
- Python 编译器与解释器
Python 编译器与解释器 Python的环境我们已经搭建好了,可以开始学习基础知识了.但是,在此之前,还要先说说编译器与解释器相关的内容. 如果这部分内容,让你觉得难以理解或不能完全明白,可以暂时 ...
- 还在用SVN的人,要不要学Git?
还在用SVN的人,要不要学Git? 提出这个问题,是因为很多小伙伴还不会使用Git. 在Git之前,是SVN的天下. SVN诞生于2001年,由于较为先进的管理方式而迅速取代了CVS. 很多80后小伙 ...
- 深入探究js中的隐式变量声明
前两天遇到的问题,经过很多网友的深刻讨论,终于有一个相对可以解释的通的逻辑了,然后我仔细研究了一下相关的点,顺带研究了一下js中的隐式变量. 以下文章中提到的隐式变量都是指没有用var,let,con ...
- httpd2.4
更换网站主页目录 1.在httpd.conf文件中更改documentroot为新的路径,并为其相应的路径给与相应的权限. Documentroot "/www/http" < ...
- [ngclass]、[ngstyle]、管道
[ngclass] 动态改变一个元素的class ts: public classcolor:boolean=false; public list:any = [{title:"新闻1&qu ...
- ng 图片的引用
对于图片的引用有两种类型 本地 业务逻辑中(使用url) 本地中图片需要存放在静态资源夹assets中下新建的文件夹images文件夹中 eg:images文件夹中有一张01.png 的图片 显示本地 ...
- 解决MVC中Model上的特性在EF框架刷新时清空的问题
MVC中关于前端数据的效验一般都是通过在Model中相关的类上打上特性来实现. 但是在我们数据库发生改变,EF框架需要刷新时会把我们在Model上的特性全部清除,这样的话,我们前端的验证就会失效. 因 ...
- 【TencentOS tiny】又有一个操作系统开源
新闻 2019年9月18日,腾讯宣布将开源 自主研发的轻量级物联网实时操作系统TencentOS tiny.相比市场上其它系统,腾讯TencentOS tiny在资源占用.设备成本.功耗管理以及安全稳 ...
- .Net下MoongoDB的简单调用
1.安装.Net 驱动:Install-Package MongoDB.Driver 2.数据插入 //新建Person测试类 public class Person { public long Id ...