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. [Python3 填坑] 013 几个类相关函数的举例

    目录 1. print( 坑的信息 ) 2. 开始填坑 2.1 issubclass() 2.2 isinstance() 2.3 hasattr() 2.4 getattr() 2.5 setatt ...

  2. ls命令输出文件的绝对路径

    find $PWD | xargs ls -ld 再结合 grep 筛选

  3. 【学习总结】cpu缓存

    参考链接: cpu缓存java性能问题初探 高速缓存 在内存与cpu寄存器之间,还有一块区域叫做cpu高速缓存,即我们常常说的cache. cache分为L1.L2.L3三级缓存,速度递减,离cpu越 ...

  4. 141-FMC141-4路 250Msps/16bits ADC, FMC板卡

    FMC141-4路 250Msps/16bits ADC, FMC板卡 一.产品概述: 本板卡基于 FMC 标准板卡,实现 4 路 16-bit/250Msps ADC 功能.遵循 VITA 57 标 ...

  5. 一、免费API调用

    一.免费API调用: 免费天气api接口 JS调用示例 <!DOCTYPE html> <html lang="zh-CN"> <head> & ...

  6. Codecraft-17 and Codeforces Round #391 - C

    题目链接:http://codeforces.com/contest/757/problem/C 题意:给定n个gym和m个Pokemon的类型,然后给你每个gym内的Pokemon未进化之前的类型, ...

  7. 初学Java 从控制台读取输入

    代码 import java.util.Scanner; public class ComputeArea { public static void main(String[] args) { Sca ...

  8. Center OS 7

    1:关闭防火墙 systemctl stop iptables.service 2:禁止开启启动 systemctl disable firewalld.service 3:查看防火墙 firewal ...

  9. Go 迭代切片

    迭代切片有两种方式: 1. 使用 for range 迭代切片   // 其长度和容量都是 4 个元素 slice := [], , , } // 迭代每一个元素,并显示其值 for index, v ...

  10. mysql查找表名

    SELECT *FROM information_schema.TABLESWHERE 1=1 AND table_name LIKE '%order%' AND table_comment like ...