《图解设计模式》读书笔记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 ...
随机推荐
- opencv部署服务器报错
报错内容: ImportError: libSM.so.6: cannot open shared object file: No such file or directory 解决办法: sudo ...
- 11 (H5*) js第1天 基本数据类型、变量
目录 1: js的介绍 2:写js代码注意的地方 3:变量 4:变量的命名和作用 5:变量的类型 6:Number类型 7:string类型 8:类型转换 9:操作符号 复习 <script& ...
- 【Jmeter】利用Jmeter+ant+Jenkins 搭建 接口&性能测试 持续集成平台
https://www.jianshu.com/p/6ab73a95d53e https://yq.aliyun.com/articles/664329
- 基于各种基础数据结构的SPFA和各种优化
一.基于各种数据结构的SPFA 以下各个数据均为不卡SPFA的最短路模板:P3371 [模板]单源最短路径(弱化版)的测试时间 1.STL队列:用时: 1106ms / 内存: 8496KB #inc ...
- 用Emacs编写mybatis
用Emacs编写mybatis */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} ...
- Emacs中的前进后退jump-tree
Emacs中的前进后退jump-tree */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #8394 ...
- 【JMeter4.0】二、JMeter4.0安装与配置
二.安装配置JMeter jmeter是一个纯java工具,因此,JDK必不可少,现在最新版的jmeter是4.0,建议使用1.8及以上的JDK安装配置JDK,如没有,请见:[JMeter4.0]一. ...
- 各种设备在linux中的文件名
各种设备在linux中的文件名: 设备 设备在linux内的文件名 ide硬盘 /dev/ha[a-d] scs硬盘 /dev/sd[a-p] u盘 /dev/sd[a-p](与SAT ...
- 如何处理HTML5新标签的浏览器兼容性问题?
① IE8/IE7/IE6支持通过document.createElement方法产生的标签,可以利用这一特性让这些浏览器支持HTML5新标签 ② 也可以使用成熟的框架 ex:html5shim &l ...
- activiti 5.22 表结构解析及清空流程运行测试数据
1.结构设计 1.1. 逻辑结构设计 Activiti使用到的表都是ACT_开头的. ACT_RE_*: 'RE'表示repository(存储),RepositoryService接口所操作的 ...