《图解设计模式》读书笔记6-2 Chain of Responsibility模式
1. 简介
Chain of Responsibility模式是责任链模式,模式的核心就是转移责任。就好比你要去政府部门办事,A部门说你去B部门问问,B部门说你去C部门问问,C部门说我们不管...在找到正确的部门解决问题之前,这些部门一直在踢皮球。
在程序中,确实需要这样的场景:将多个对象组成一个责任链,一个请求过来了,按照它们在责任链上的顺序一个一个找出到底由谁来负责。
这个模式的好处在于弱化请求方和处理方的关联关系,让双方都可以成为独立复用的组件。
2. 示例程序
类图

代码
Trouble类是表示问题的类,其属性nubmer是问题编号。
Support以及其子类表示解决问题的类,Support是抽象父类,具体的Support类表示解决特定问题的类。
public class Trouble {
private int number; // 问题编号
public Trouble(int number) { // 生成问题
this.number = number;
}
public int getNumber() { // 获取问题编号
return number;
}
public String toString() { // 代表问题的字符串
return "[Trouble " + number + "]";
}
}
//解决问题的抽象父类
public abstract class Support {
private String name;
private Support next;
public Support(String name) {
this.name = name;
}
public Support setNext(Support next) {
this.next = next;
return next;
}
//定义解决问题的步骤
// 其中使用了抽象方法resolve,这个方法由子类实现,这是Template Method方法的体现。
public 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.");
}
}
//什么问题都不解决
public class NoSupport extends Support {
public NoSupport(String name) {
super(name);
}
protected boolean resolve(Trouble trouble) { // 解决问题的方法
return false; // 自己什么也不处理
}
}
// 可以解决编号小于limit的问题
public class LimitSupport extends Support {
private int limit;
public LimitSupport(String name, int limit) { // 构造函数
super(name);
this.limit = limit;
}
protected boolean resolve(Trouble trouble) { // 解决问题的方法
if (trouble.getNumber() < limit) {
return true;
} else {
return false;
}
}
}
//解决编号为奇数的问题
public class OddSupport extends Support {
public OddSupport(String name) { // 构造函数
super(name);
}
protected boolean resolve(Trouble trouble) { // 解决问题的方法
if (trouble.getNumber() % 2 == 1) {
return true;
} else {
return false;
}
}
}
//只能解决编号为number的问题
public class SpecialSupport extends Support {
private int number;
public SpecialSupport(String name, int number) { // 构造函数
super(name);
this.number = number;
}
protected boolean resolve(Trouble trouble) { // 解决问题的方法
if (trouble.getNumber() == number) {
return true;
} else {
return false;
}
}
}
public class Main {
public static void main(String[] args) {
Support noSupportMan = new NoSupport("noSupportMan");
Support lt2Man = new LimitSupport("lt2Man", 2);
Support specialFor5Man =
new SpecialSupport("specialFor5Man", 5);
Support lt10Man = new LimitSupport("lt10Man", 10);
Support oddMan = new OddSupport("oddMan");
Support lt15Man = new LimitSupport("lt15Man", 15);
// 一层一层深入设置职责链条
noSupportMan
.setNext(lt2Man)
.setNext(specialFor5Man)
.setNext(lt10Man)
.setNext(oddMan)
.setNext(lt15Man);
// 解决各种问题
for (int i = 0; i < 17; i++) {
noSupportMan.support(new Trouble(i));
}
}
}
//结果
[Trouble 0] is resolved by [lt2Man].
[Trouble 1] is resolved by [lt2Man].
[Trouble 2] is resolved by [lt10Man].
[Trouble 3] is resolved by [lt10Man].
[Trouble 4] is resolved by [lt10Man].
[Trouble 5] is resolved by [specialFor5Man].
[Trouble 6] is resolved by [lt10Man].
[Trouble 7] is resolved by [lt10Man].
[Trouble 8] is resolved by [lt10Man].
[Trouble 9] is resolved by [lt10Man].
[Trouble 10] is resolved by [lt15Man].
[Trouble 11] is resolved by [oddMan].
[Trouble 12] is resolved by [lt15Man].
[Trouble 13] is resolved by [oddMan].
[Trouble 14] is resolved by [lt15Man].
[Trouble 15] is resolved by [oddMan].
[Trouble 16] cannot be resolved.
3. 模式的角色和类图
角色
- Handler(处理者):定义了处理请求的接口,这个角色知道下一个Handler是谁,如果自己处理不了就会交给下一个Handler处理。本例中,由Support类扮演此角色。
- ConcreteHandler(具体的处理者):实现了具体的处理方法。由NoSupport、LimitSupport、OddSupport、SpecialSupport扮演此角色。
- Client(请求者):向处理者发送问题请求的角色,本例中由Main类扮演此角色。
类图

4. 思路拓展
弱化了发出请求的人和处理请求的人的关系
可以动态改变职责链
专注于自己的工作
模式的缺点:责任被传递,请求会延迟
《图解设计模式》读书笔记6-2 Chain of Responsibility模式的更多相关文章
- 设计模式(十四)Chain of Responsibility模式
Chain of Responsibility模式就是当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任.也就是说,当一个人被要求做什么事时,如果他可以做就自己做, ...
- CSharp设计模式读书笔记(24):访问者模式(学习难度:★★★★☆,使用频率:★☆☆☆☆)
模式角色与结构: 示例代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; ...
- CSharp设计模式读书笔记(23):模板方法模式(学习难度:★★☆☆☆,使用频率:★★★☆☆)
模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中.模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 模式角色与结构: 实现代码: using System; ...
- CSharp设计模式读书笔记(22):策略模式(学习难度:★☆☆☆☆,使用频率:★★★★☆)
策略模式(Strategy Pattern):定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy). 模式角色与结构: ...
- CSharp设计模式读书笔记(21):状态模式(学习难度:★★★☆☆,使用频率:★★★☆☆)
模式角色与结构: 示例代码:(本示例在具体状态类中实现状态切换,也可以在环境类中实现状态切换.状态模式一定程度上违背开闭原则) using System; using System.Collectio ...
- CSharp设计模式读书笔记(19):备忘录模式(学习难度:★★☆☆☆,使用频率:★★☆☆☆)
备忘录模式(Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态.它是一种对象行为型模式,其别名为Tok ...
- CSharp设计模式读书笔记(17):迭代器模式(学习难度:★★★☆☆,使用频率:★★★★★)
迭代器模式(Iterator Pattern):提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(Cursor). 模式角色与结构: 实现代码: using System; us ...
- CSharp设计模式读书笔记(15):命令模式(学习难度:★★★☆☆,使用频率:★★★★☆)
命令模式(Command Pattern):将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及支持可撤销的操作.命令模式是一种对象行为型模式,其别名为 ...
- CSharp设计模式读书笔记(13):代理模式(学习难度:★★★☆☆,使用频率:★★★★☆)
代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问. 模式角色与结构: 示例代码: using System; using System.Collections.Generi ...
- CSharp设计模式读书笔记(11):外观模式(学习难度:★☆☆☆☆,使用频率:★★★★★)
定义: 外观模式:为子系统中的一组接口提供一个统一的入口.外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 模式角色与结构: 示例代码: using System; using Sys ...
随机推荐
- Java实现红黑树
转自:http://www.cnblogs.com/skywang12345/p/3624343.html 红黑树的介绍 红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉 ...
- POJ-1679.The Unique MST.(Prim求次小生成树)
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 39561 Accepted: 14444 ...
- 最小生成树基础算法(Prim + Krustal)
最小生成树问题的引入: 对于一个无向图G(V, E),需要用图中的n - 1条边连接图中的n个顶点并且不产生回路所产生的树就叫做生成树,其中权值总和最小的就是最小生成树. 如何求解最小生成树问题: 譬 ...
- [LOJ3123] CTSC2019重复
Description 给定一个⻓为 n 的字符串 s , 问有多少个⻓为 m 的字符串 t 满足: 将 t 无限重复后,可以从中截出一个⻓度为 n 且字典序比 s 小的串. m ≤ 2000 n ≤ ...
- [洛谷P3261] [JLOI2015]城池攻占(左偏树)
不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...
- 玩爆你的手机联系人--T9搜索(一)
自己研究了好几天联系人的T9搜索算法, 先分享出来给大家看看. 欢迎不吝赐教.假设有大神有更好的T9搜索算法, 那更好啊,大家一起研究研究,谢谢. 第一部分是比較简单的获取手机联系人. 获取 ...
- NGUI的输入框制作(attach- input filed script的使用)
一,我们添加一个sprite,给这个sprite添加一个box collider ,然后添加input filed script,如下图: 二,我们给sprite添加一个child的label,然后绑 ...
- 265-Keystone II JESD204B 66AK2L06 评估模块 (现行) XEVMK2LX
Keystone II JESD204B 66AK2L06 评估模块 (现行) XEVMK2LX 一. 板卡概述The XEVMK 2LX is a full-featured evaluation ...
- weblogic启动脚本
DATE=`date +%Y%m%d%H%M%S` user=`whoami` logDir=/app/logs/sguap_admin #启动日志存放路径sguap是例子系统简称# logDestd ...
- 【串线篇】Mybatis缓存之二级缓存
1.应用 二级缓存:namespace级别的缓存:SqlSession关闭或者提交以后有效 一级缓存:SqlSession关闭或者提交以后,一级缓存的数据会放在二级缓存中: 二级缓存的使用:mybat ...