一口一口啃完Java中的24种设计模式---责任链模式


责任链模式总结

下面补充上图中的责任链模式 UML 图,责任链模式 Demo、 Android 源码中的责任链模式—事件分发。

责任链模式的UML图

Demo

在一家公司中,主任、副董事长、董事长、董事会都可以处理采购单,区别是每一个角色能够处理的采购单金额不同,采购订单需要一级一级处理,当已经被某一角色处理完了,就不会在交给下一个角色处理,写一个采购单处理系统。

针对上述需求,分析一下:当金额没有到达某一角色的处理的下限时,他是不负责处理的,当金额超过他负责处理的上限时,他就处理不了了,就会交给他的上级去处理,只有采购单金额刚好在他处理的范围之内,他才会去处理。那么这种结构就是一个典型的链式处理结构,并且无论订单多大,董事会总是可以处理的,所以这也是一个纯的责任链结构

我们用责任链模式来处理。先上 UML 图:

根据 UML 图中的过程角色,代码如下:

抽象处理者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 抽象处理者
*
* @author: fanyuzeng on 2018/3/24 10:43
*/
public abstract class Approver {
/**
* 后继处理者
*/
public Approver mSuccessor;
protected String mName;
/**
* 抽象处理方法
*
* @param purchaseRequest 采购单实体类
*/
public abstract void processPurchase(PurchaseRequest purchaseRequest);
}

具体处理者

主任:

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
/**
* 具体处理者:主任 <p>
* 处理金额: [0,10k)
*
* @author: fanyuzeng on 2018/3/24 10:50
*/
public class Director extends Approver {
public Director(String name) {
mName = name;
}
@Override
public void processPurchase(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getAmount() >= 0 && purchaseRequest.getAmount() < 10000) {
System.out.println("我是主任" + mName + ",采购单编号:" + purchaseRequest.getNum() + ",金额:" + purchaseRequest.getAmount()
+ ",用于购买" + purchaseRequest.getPurpose()+",这笔采购单我来处理。");
} else {
System.out.println("我是主任" + mName + ",采购单编号:" + purchaseRequest.getNum() + ",金额:" + purchaseRequest.getAmount()+"太大,我处理不了,交给下一级处理。");
mSuccessor.processPurchase(purchaseRequest);
}
}
}

董事长:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 具体处理者:董事长 <p>
* 处理金额: [10k,100k)
*
* @author: fanyuzeng on 2018/3/24 10:51
*/
public class Chairman extends Approver {
public Chairman(String name) {
mName = name;
}
@Override
public void processPurchase(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getAmount() >= 10000 && purchaseRequest.getAmount() < 100000) {
System.out.println("我是董事长" + mName + ",采购单编号:" + purchaseRequest.getNum() + ",金额:" + purchaseRequest.getAmount()
+ ",用于购买" + purchaseRequest.getPurpose() + ",这笔采购单我来处理。");
} else {
System.out.println("我是董事长" + mName + ",采购单编号:" + purchaseRequest.getNum() + ",金额:" + purchaseRequest.getAmount() + "太大,我处理不了,交给下一级处理。");
mSuccessor.processPurchase(purchaseRequest);
}
}
}

董事会:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 具体处理者:董事会 <p>
* 处理金额: [100k,+ infinity)
*
* @author: fanyuzeng on 2018/3/24 10:54
*/
public class BoardOfDirectors extends Approver {
public BoardOfDirectors(String name) {
mName = name;
}
@Override
public void processPurchase(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getAmount() >= 100000) {
System.out.println("我是董事长" + mName + ",采购单编号:" + purchaseRequest.getNum() + ",金额:" + purchaseRequest.getAmount()
+ ",用于购买" + purchaseRequest.getPurpose() + ",这笔采购单我来处理。");
}
}
}

待处理需求实体类

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
/**
* 采购单 Module
*
* @author: fanyuzeng on 2018/3/24 10:48
*/
public class PurchaseRequest {
/**
* 采购金额
*/
private long amount;
/**
* 采购编号
*/
private int num;
/**
* 采购用途
*/
private String purpose;
public PurchaseRequest(long amount, int num, String purpose) {
this.amount = amount;
this.num = num;
this.purpose = purpose;
}
//getter and setter

客户端类(测试类)

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
/**
* @author: fanyuzeng on 2018/2/24 11:23
*/
public class Test {
private static ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
final PurchaseRequest purchaseRequest1 = new PurchaseRequest(10000000, 12580, "98K");
final PurchaseRequest purchaseRequest2 = new PurchaseRequest(8000, 12581, "M16");
final PurchaseRequest purchaseRequest3 = new PurchaseRequest(70000, 12582, "AUG");
final Approver director = new Director("Jack");
Approver chairmain = new Chairman("Tom");
Approver boardOfDirectors = new BoardOfDirectors("NiubilityBoardOfDirectors");
director.mSuccessor = chairmain;
chairmain.mSuccessor = boardOfDirectors;
mExecutorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("---------purchaseRequest1 start-------------------");
director.processPurchase(purchaseRequest1);
System.out.println("---------purchaseRequest1 end---------------------" + "\n");
}
});
mExecutorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("---------purchaseRequest2 start-------------------");
director.processPurchase(purchaseRequest2);
System.out.println("---------purchaseRequest2 end---------------------" + "\n");
}
});
mExecutorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("---------purchaseRequest3 start-------------------");
director.processPurchase(purchaseRequest3);
System.out.println("---------purchaseRequest3 end---------------------");
}
});
}
}

此时采购单处理流程:主任 jack —> 董事长 tom —> 董事会

出入内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
---------purchaseRequest1 start-------------------
我是主任Jack,采购单编号:12580,金额:10000000太大,我处理不了,交给下一级处理。
我是董事长Tom,采购单编号:12580,金额:10000000太大,我处理不了,交给下一级处理。
我是董事长NiubilityBoardOfDirectors,采购单编号:12580,金额:10000000,用于购买98K,这笔采购单我来处理。
---------purchaseRequest1 end---------------------
---------purchaseRequest2 start-------------------
我是主任Jack,采购单编号:12581,金额:8000,用于购买M16,这笔采购单我来处理。
---------purchaseRequest2 end---------------------
---------purchaseRequest3 start-------------------
我是主任Jack,采购单编号:12582,金额:70000太大,我处理不了,交给下一级处理。
我是董事长Tom,采购单编号:12582,金额:70000,用于购买AUG,这笔采购单我来处理。
---------purchaseRequest3 end---------------------

动态扩展

假如公司采购单金额在 1k 范围以内的很多,主任又太忙了,所以他招了一个女实习 Rose 生来给他干,以后的采购单先给实习生去处理,如果她处理不了,在给主任。此时这个我们需要改变这个系统的处理链的逻辑。

首先增加女实习生的 Approve

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @author: fanyuzeng on 2018/3/24 11:41
*/
public class Intern extends Approver {
public Intern(String name) {
mName = name;
}
@Override
public void processPurchase(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getAmount() >= 0 && purchaseRequest.getAmount() < 10000) {
System.out.println("我是实习生" + mName + ",采购单编号:" + purchaseRequest.getNum() + ",金额:" + purchaseRequest.getAmount()
+ ",用于购买" + purchaseRequest.getPurpose()+",这笔采购单我来处理。");
} else {
System.out.println("我是实习生" + mName + ",采购单编号:" + purchaseRequest.getNum() + ",金额:" + purchaseRequest.getAmount()+"太大,我处理不了,交给下一级处理。");
mSuccessor.processPurchase(purchaseRequest);
}
}
}

然后在客户端修改:

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
/**
* @author: fanyuzeng on 2018/2/24 11:23
*/
public class Test {
private static ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
final PurchaseRequest purchaseRequest1 = new PurchaseRequest(10000000, 12580, "98K");
final PurchaseRequest purchaseRequest2 = new PurchaseRequest(8000, 12581, "M16");
final PurchaseRequest purchaseRequest3 = new PurchaseRequest(70000, 12582, "AUG");
final PurchaseRequest purchaseRequest4 = new PurchaseRequest(500, 12583, "止痛药");
final Approver intern = new Intern("Rose");
Approver director = new Director("Jack");
Approver chairmain = new Chairman("Tom");
Approver boardOfDirectors = new BoardOfDirectors("NiubilityBoardOfDirectors");
intern.mSuccessor = director;
director.mSuccessor = chairmain;
chairmain.mSuccessor = boardOfDirectors;
mExecutorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("---------purchaseRequest1 start-------------------");
intern.processPurchase(purchaseRequest1);
System.out.println("---------purchaseRequest1 end---------------------" + "\n");
}
});
mExecutorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("---------purchaseRequest2 start-------------------");
intern.processPurchase(purchaseRequest2);
System.out.println("---------purchaseRequest2 end---------------------" + "\n");
}
});
mExecutorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("---------purchaseRequest3 start-------------------");
intern.processPurchase(purchaseRequest3);
System.out.println("---------purchaseRequest3 end---------------------");
}
});
mExecutorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("---------purchaseRequest4 start-------------------");
intern.processPurchase(purchaseRequest4);
System.out.println("---------purchaseRequest4 end---------------------");
}
});
}
}

在客户端重新修改采购单处理链:

  1. 增加 Intern 对象 Rouse
  2. 将所有采购统统交给 Rouse 处理,而不是之前的主任 Jack

此时采购单处理流程:实习生 Rose —> 主任 jack —> 董事长 tom —> 董事会

此时的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
---------purchaseRequest1 start-------------------
我是实习生Rose,采购单编号:12580,金额:10000000太大,我处理不了,交给下一级处理。
我是主任Jack,采购单编号:12580,金额:10000000太大,我处理不了,交给下一级处理。
我是董事长Tom,采购单编号:12580,金额:10000000太大,我处理不了,交给下一级处理。
我是董事长NiubilityBoardOfDirectors,采购单编号:12580,金额:10000000,用于购买98K,这笔采购单我来处理。
---------purchaseRequest1 end---------------------
---------purchaseRequest2 start-------------------
我是实习生Rose,采购单编号:12581,金额:8000,用于购买M16,这笔采购单我来处理。
---------purchaseRequest2 end---------------------
---------purchaseRequest3 start-------------------
我是实习生Rose,采购单编号:12582,金额:70000太大,我处理不了,交给下一级处理。
我是主任Jack,采购单编号:12582,金额:70000太大,我处理不了,交给下一级处理。
我是董事长Tom,采购单编号:12582,金额:70000,用于购买AUG,这笔采购单我来处理。
---------purchaseRequest3 end---------------------
---------purchaseRequest4 start-------------------
我是实习生Rose,采购单编号:12583,金额:500,用于购买止痛药,这笔采购单我来处理。
---------purchaseRequest4 end---------------------

这就是 纯的责任链模式的一个例子。至于不纯的责任链模式,在 Android 源码中有一个跟好的体现,就是 事件分发机制。

Android 源码中的责任链模式—事件分发机制

这里简述,不深入分析。

当用户触摸屏幕时,Android 系统会产生一个 MotionEvent 对象用于表示触摸事件,然后这个 MotionEvent 会从 ViewTree 的顶部从上而下的分发,经过 Windows —> Activity —> ViewGroup —> View.

ViewGroup 把 MotionEvent 不断的递归分发,查找可以消耗这个事件的 View (ViewGroup),然后被 onTouchEvent 方法所处理。 这个过程也是一个责任链的模式。

但是要注意的是:并且这是一个不纯的责任链模式,因为触摸事件 MotionEvent 可能没有任何一个 view 能够消耗它。

共82.3k字
0%
.gt-container a{border-bottom: none;}