Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.(将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。)

职责链模式常用在框架开发中,用来实现框架的过滤器拦截器功能,让框架的使用者在不需要修改框架源码的情况下,添加新的过滤拦截功能。这也体现了之前讲到的对扩展开放、对修改关闭的设计原则。

1 责任链模式 UML

图片来源于《Android 源码设计模式解析与实战》

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
54
55
56
57
58
59
60
61
62
63
public abstract class Handler {
protected Handler successor = null;

public void setSuccessor(Handler successor) {
this.successor = successor;
}

public abstract void handle();
}

public class HandlerA extends Handler {
@Override
public void handle() {
boolean handled = false;
//...
if (!handled && successor != null) {
successor.handle();
}
}
}

public class HandlerB extends Handler {
@Override
public void handle() {
boolean handled = false;
//...
if (!handled && successor != null) {
successor.handle();
}
}
}

public class HandlerChain {
private Handler head = null;
private Handler tail = null;

public void addHandler(Handler handler) {
handler.setSuccessor(null);
if (head == null) {
//链中还没有处理者
head = handler;
tail = handler;
return;
}
// 将新的 hadler 添加到末尾 类似于 链表的 next 指针
tail.setSuccessor(handler);
// 并用 tail 标记
tail = handler;
}

public void handle() {
if (head != null) {
head.handle();
}
}
}

public static void main(String[] args) {
HandlerChain chain = new HandlerChain();
chain.addHandler(new HandlerA());
chain.addHandler(new HandlerB());
chain.handle();
}

这种是最简单好理解的责任链模式的例子,每个 handler 执行完都回去执行 successor(相当于 next 指针) 的方法。这种方式需要在每个实现类中手动的调用 successor ,我们还可以做一下封装,将这部分逻辑交给父类,子类只需要控制是否需要继续执行下一个 succesor 即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class Handler {
protected Handler successor = null;

public void setSuccessor(Handler successor) {
this.successor = successor;
}

public final void handle() {
boolean handled = doHandle();
if (successor != null && !handled) {
successor.handle();
}
}

protected abstract boolean doHandle();
}

Handler 做如上修改,在 handle() 中做链表的处理,子类只需要返回是否需要继续执行,HandlerChain 不变。

1
2
3
4
5
6
7
8
public class HandlerA extends Handler {
@Override
protected boolean doHandle() {
boolean handled = false;
//...
return handled;
}
}

当然还有一种很好理解的方式,将所有的 handler 添加到一个 List 当中,循环执行。

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
public interface IHandler {
boolean handle();
}

public class HandlerA implements IHandler {
@Override
public boolean handle() {
boolean handled = false;
//...
return handled;
}
}

public class HandlerChain {
private List<IHandler> handlers = new ArrayList<>();

public void addHandler(IHandler handler) {
this.handlers.add(handler);
}

public void handle() {
for (IHandler handler : handlers) {
boolean handled = handler.handle();
if (handled) {
break;
}
}
}
}

有些情况是需要在每一级做一些处理,可以修改一下返回,就可以实现。

2 简单实现

假如需要报销一笔费用,首先给将报销单给 部门组长 ,组长权限不够交给 部门主管 ,主管权限不够交给 经理 ,经理不够交给 老板 。这个过程就像一个责任链,我们只需要将报销单交给部门组长,具体谁报销不需要关系,我们在乎的只有结果… 责任链模式很好的将处理者与发起者解耦,避免写出成堆的 if - else

由于这里有统一的判断条件,那就是金额,所以将是否拦截统一交给父类,而不是子类处理拦截。

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// 抽象父类
public abstract class Leader {
protected Leader superior = null;

public void setSuccessor(Leader successor) {
this.superior = successor;
}

public final void handleRequest(int money) {
if (money <= limit()) {
handle(money);
} else {
if (superior != null) {
superior.handleRequest(money);
}
}
}

protected abstract int limit();
protected abstract void handle(int money);
}

public class GroupLeader extends Leader {
@Override
protected int limit() {
return 1000;
}

@Override
protected void handle(int money) {
System.out.println("组长批复报销" + money + "元");
}
}

public class Director extends Leader {
@Override
protected int limit() {
return 5000;
}

@Override
protected void handle(int money) {
System.out.println("主管批复报销" + money + "元");
}
}
// 省略 Manager 与 Boss 类

// 处理链表类
public class LeaderChain {
private Leader head = null;
private Leader tail = null;

public void addLeader(Leader handler) {
handler.setSuccessor(null);
if (head == null) {
//证明链中还没有处理者
head = handler;
tail = handler;
return;
}
// 将新的 hadler 添加到末尾 类似于 链表的 next 指针
tail.setSuccessor(handler);
// 并用 tail 标记
tail = handler;
}

public void handleRequest(int money) {
if (head != null) {
head.handleRequest(money);
}
}
}

LeaderChain chain = new LeaderChain();
chain.addLeader(new GroupLeader());
chain.addLeader(new Director());
chain.addLeader(new Manager());
chain.addLeader(new Boss());
chain.handleRequest(10000);

3 Android 中的责任链模式

  1. Touch 事件

    事件分发(源码分析)

  2. OkHTTP 拦截器

    重点在于每个拦截器都换调用 chain.proceed(request) 调用下一个拦截器等待返回。OkHttp源码分析(二) 责任链实现篇 RealInterceptorChain

感谢

设计模式之美

《Android 源码设计模式解析与实战》

以及上文中的链接