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模式的更多相关文章

  1. 设计模式(十四)Chain of Responsibility模式

    Chain of Responsibility模式就是当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任.也就是说,当一个人被要求做什么事时,如果他可以做就自己做, ...

  2. CSharp设计模式读书笔记(24):访问者模式(学习难度:★★★★☆,使用频率:★☆☆☆☆)

    模式角色与结构: 示例代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

  3. CSharp设计模式读书笔记(23):模板方法模式(学习难度:★★☆☆☆,使用频率:★★★☆☆)

    模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中.模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 模式角色与结构: 实现代码: using System; ...

  4. CSharp设计模式读书笔记(22):策略模式(学习难度:★☆☆☆☆,使用频率:★★★★☆)

    策略模式(Strategy Pattern):定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy). 模式角色与结构: ...

  5. CSharp设计模式读书笔记(21):状态模式(学习难度:★★★☆☆,使用频率:★★★☆☆)

    模式角色与结构: 示例代码:(本示例在具体状态类中实现状态切换,也可以在环境类中实现状态切换.状态模式一定程度上违背开闭原则) using System; using System.Collectio ...

  6. CSharp设计模式读书笔记(19):备忘录模式(学习难度:★★☆☆☆,使用频率:★★☆☆☆)

    备忘录模式(Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态.它是一种对象行为型模式,其别名为Tok ...

  7. CSharp设计模式读书笔记(17):迭代器模式(学习难度:★★★☆☆,使用频率:★★★★★)

    迭代器模式(Iterator Pattern):提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(Cursor). 模式角色与结构: 实现代码: using System; us ...

  8. CSharp设计模式读书笔记(15):命令模式(学习难度:★★★☆☆,使用频率:★★★★☆)

    命令模式(Command Pattern):将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及支持可撤销的操作.命令模式是一种对象行为型模式,其别名为 ...

  9. CSharp设计模式读书笔记(13):代理模式(学习难度:★★★☆☆,使用频率:★★★★☆)

    代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问. 模式角色与结构: 示例代码: using System; using System.Collections.Generi ...

  10. CSharp设计模式读书笔记(11):外观模式(学习难度:★☆☆☆☆,使用频率:★★★★★)

    定义: 外观模式:为子系统中的一组接口提供一个统一的入口.外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 模式角色与结构: 示例代码: using System; using Sys ...

随机推荐

  1. java.lang.IllegalStateException: Cannot forward after response has been committed

    jjava.lang.IllegalStateException: Cannot forward after response has been committed at org.apache.cat ...

  2. Self-Attention 和 Transformer

    1.Self-Attention 之前的RNN输入是难以并行化的,我们下一个输入可能依赖前一个输出,只有知道了前面的输出才能计算后面的输出. 于是提出了 self-attention ,但是这时候 $ ...

  3. CentOS7和Ubuntu18.10下运行Qt Creator出现cannot find -lGL的问题的解决方案

    解决方法:缺少相应的opengl的库,需要安装opengl库 一.Ubuntu下解决Qt5.11.1 cannot find -lGL 有两种原因: 一种是没有按照libGL库,那么就安装: sudo ...

  4. mysql: "Warning: Using a password on the command line interface can be insecure." 解决方法

    错误重现: 命令行或者shell脚本中执行以下命令,如果您当前服务器mysql版本是大于5.6的,则会出现警告:Warning: Using a password on the command lin ...

  5. java虚拟机笔记-1

    java虚拟机学习笔记 Java技术的核心就是Java虚拟机,因为所有的Java程序都在虚拟机上运行.Java程序的运行需要Java虚拟机.Java API和Java Class文件的配合.Java虚 ...

  6. jQuery easyUI 使用 datagrid 表格

    获取后台数据依旧是使用一般处理程序(ashx) ,分页上添加一个函数(pagerFilter(data)) 前端代码: <%@ Page Language="C#" Auto ...

  7. Panabit的各种配置文件

    Panabit的各种配置文件 1.启动配置文件路径:/etc/rc.local作用:这个文件里的内容是BSD启动后会自动执行的命令默认配置如下:fsck -y -t ufs /dev/ad0s2a & ...

  8. 【JAVA】eclipse-使用入门及常用快捷键

    目录 下载与安装 HelloWorld 新建项目 视图与视窗 快捷键 个性化设置 导入项目 jar包 下载与安装 下载 网址:官网下载 注意: 下载javaee版 注意与本机的java环境相匹配,32 ...

  9. JavaScript原型&原型链

    原型&原型对象 先来一段简单的代码: function Fun(name) { this.name = name } var obj = new Fun('obj') JavaScript中的 ...

  10. route - 显示 / 操作IP选路表

    总览 SYNOPSIS route [-CFvnee] route [-v] [-A family] add [-net|-host] target [netmask Nm] [gw Gw] [met ...