责任链模式

​ 将能够处理同一类请求的对象连成一条链,所提交的请求将沿着这条链传递,链上的对象逐个判断是否有能力处理该请求,如果有则处理,如果没有则将请求传递给下一个对象处理。

场景举例

  • 生活场景

    在学校时,请假条的审批过程:

    1. 如果请假小于3天,辅导员直接批准
    2. 如果请假大于等于3天小于10天,需院长审批
    3. 如果请假大于等于10天小于30天,校长审批
    4. 请假被拒绝
  • 开发场景

    ​ Java中,异常机制就是一种责任链模式。一个try可以对应多个catch,当第一个catch不匹配时,则自动跳到第二个catch。

    上述就是一个责任链,各级对象都有处理请求能力但处理能力不同,请求一直沿着责任链传递下去。

模式结构

  • Requester请求者:请求类
  • AbstractHandler抽象处理者:由于各级对象都具有相同的处理能力,所以有一个公共的抽象父接口
  • ConcreteHandler具体处理者:具有不同处理能力的处理类

代码

Requester请求者

1
2
3
4
5
6
7
8
9
/**
* 请求者发出请假:学生类
*/
@Date
public class Student {
private String name;
private int leaveDays;
private String reason;
}

AbstractHandler抽象处理者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 抽象处理者:领导类
*/
public abstract class Leader {
protected String name;
protected Leader nextHandler;//责任链上的后继对象
public Leader(String name) {
super();
this.name = name;
}
//设定责任链上的后继对象
public void setNextHandler(Leader nextHandler) {
this.nextHandler = nextHandler;
}
// 处理请求的核心的业务方法
protected abstract void handleRequest(Student student);
}

ConcreteHandler抽象处理者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* 具体处理者:辅导员类
*/
public class Assistant extends Leader {
public Assistant(String name) {
super(name);
}
@Override
protected void handleRequest(Student student) {
if(student.getLeaveDays()<3){
System.out.println("辅导员:"+this.name+"批准"+student.getName()+"的请假");
}else{
if(this.nextHandler!=null){
this.nextHandler.handleRequest(student);
}
}
}
}
/**
* 具体处理者:院长类
*/
public class Dean extends Leader {
public Dean(String name) {
super(name);
}
@Override
protected void handleRequest(Student student) {
if(student.getLeaveDays()<10){
System.out.println("院长:"+this.name+"批准"+student.getName()+"的请假");
}else{
if(this.nextHandler!=null){
this.nextHandler.handleRequest(student);
}
}
}
}

/**
* 具体处理者:校长类
*/
public class HeadMaster extends Leader {
public HeadMaster(String name) {
super(name);
}
@Override
protected void handleRequest(Student student) {
if(student.getLeaveDays()<30){
System.out.println("校长:"+this.name+"批准"+student.getName()+"的请假");
}else{
System.out.println("请假被拒绝");
}
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Client {
public static void main(String[] args) {
Leader assistant=new Assistant("张三");
Leader dean=new Dean("李四");
Leader headMaster=new HeadMaster("王五");
//组织责任链对象的关系
assistant.setNextHandler(dean);
dean.setNextHandler(headMaster);
//开始请假操作
Student student=new Student("赵六",15,"回家探亲");
assistant.handleRequest(student);
}
}

非链表实现责任链

​ 上述代码通过链表的方式定义责任链,而往往通过集合、数组生成责任链更加实用。实际上,在很多项目中,每个具体的Handler并不是由开发团队定义的,而是项目上线后由外部单位追加的,所以使用链表方式定义COR链就很困难。

总结

​ 责任链模式对于请求的处理是不知道最终处理者是谁,所以是运行动态寻找并指定;而命令模式中对于命令的处理时在创建命令是已经显式或隐式绑定了接收者。

使用场景

  1. 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定
  2. 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
  3. 处理一个请求的对象集合应被动态指定

缺点

​ 对于每一个请求都需要遍历职责链,性能是个问题