设计模式之职责链模式(卷十三)

设计模式之职责链模式。

在一个系统中,一个请求可以被多个对象所处理,职责链通过类似链表的方式将多个处理对象连接在一起,客户端沿着自定义的顺序传递请求。职责链模式降低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这个请求

0x00 组成部分

  • Handler:抽象处理者,声明处理请求的方法,同时持有下一个处理者的引用
  • ConcreteHandler:具体处理者,通常有多个,实现了处理请求的方法,也可以选择性的处理部分请求,再传递给下一个处理者继续处理。
  • Client:客户端负责创建具体的链。

架构UML图如下。

0x01 示例代码

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package com.kkk.pattern.chain;

/**
* 官员接口,充当抽象请求处理者。
* Created by z3jjlzt on 2018/1/11.
*/

public abstract class Official {
protected Official successor;

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

//处理请求
public abstract void handleReq(int level);
}

/**
* 县令,充当具体处理者。
* Created by z3jjlzt on 2018/1/11.
*/

public class Magistrate extends Official{

@Override
public void handleReq(int level) {
if (level <= Lawsuit.LEVEL_1) {
System.out.println("本县令又可以受贿了,好开心!!!");
} else {
System.out.println("这么大的案件,我可不敢自己管,感觉交给上司!!!");
successor.handleReq(level);
}
}
}

/**
* 总督,充当具体处理者。
* Created by z3jjlzt on 2018/1/11.
*/

public class Governor extends Official {
@Override
public void handleReq(int level) {
if (level <= Lawsuit.LEVEL_2) {
System.out.println("本总督好想处理大案件啊,可是却天天处理这些个破案件,真浪费了我的才华!!!");
} else {
System.out.println("好想自己处理啊,可是我没权利管,好可惜。。。");
successor.handleReq(level);
}
}
}

/**
* 丞相,充当具体处理者。
* Created by z3jjlzt on 2018/1/11.
*/

public class PrimeMinister extends Official {
@Override
public void handleReq(int level) {
if (level <= Lawsuit.LEVEL_3) {
System.out.println("本相今天判他个100年!!!");
} else {
System.out.println("泱泱大国可不能毁在我手里呀,感觉通知圣上!!!");
successor.handleReq(level);
}
}
}

/**
* 皇帝,充当具体处理者。
* Created by z3jjlzt on 2018/1/11.
*/

public class Emperor extends Official {
private Random random = new Random();

//这是个昏君,处理国家大事也看心情。
private int mood;

public int getMood() {
mood = random.nextInt(3);
return mood;
}

@Override
public void handleReq(int level) {
switch (getMood()) {
case 0:
System.out.println("寡人今日心情欠佳,无心理会朝事");
break;
case 1:
System.out.println("容我看看是谁吃了豹子胆,胆敢当卖国贼!!");
break;
default:
System.out.println("陛下在睡觉!!!");
break;
}

}
}

**
* 官司分类.
* Created by z3jjlzt on 2018/1/11.
*/
public class Lawsuit {
public static final int LEVEL_1 = 1;
public static final int LEVEL_2 = 2;
public static final int LEVEL_3 = 3;
public static final int LEVEL_4 = 4;
}

/**
* 客户端,负责创建职责链。
* Created by z3jjlzt on 2018/1/11.
*/

public class Client {
public static void main(String[] args) {
Official o1,o2,o3,o4;
o1 = new Magistrate();
o2 = new Governor();
o3 = new PrimeMinister();
o4 = new Emperor();
o1.setSuccessor(o2);
o2.setSuccessor(o3);
o3.setSuccessor(o4);

o1.handleReq(1);
System.out.println();
o4.handleReq(2);
System.out.println();
o3.handleReq(3);
System.out.println();
o1.handleReq(4);
System.out.println();
o1.handleReq(4);
System.out.println();
o1.handleReq(4);
System.out.println();
o1.handleReq(4);
}
}
随机一个结果:
本县令又可以受贿了,好开心!!!

寡人今日心情欠佳,无心理会朝事

本相今天判他个100年!!!

这么大的案件,我可不敢自己管,感觉交给上司!!!
好想自己处理啊,可是我没权利管,好可惜。。。
泱泱大国可不能毁在我手里呀,感觉通知圣上!!!
容我看看是谁吃了豹子胆,胆敢当卖国贼!!

这么大的案件,我可不敢自己管,感觉交给上司!!!
好想自己处理啊,可是我没权利管,好可惜。。。
泱泱大国可不能毁在我手里呀,感觉通知圣上!!!
寡人今日心情欠佳,无心理会朝事

这么大的案件,我可不敢自己管,感觉交给上司!!!
好想自己处理啊,可是我没权利管,好可惜。。。
泱泱大国可不能毁在我手里呀,感觉通知圣上!!!
陛下在睡觉!!!

这么大的案件,我可不敢自己管,感觉交给上司!!!
好想自己处理啊,可是我没权利管,好可惜。。。
泱泱大国可不能毁在我手里呀,感觉通知圣上!!!
寡人今日心情欠佳,无心理会朝事

0xff 总结

  • 优点:无需知道请求具体由哪个处理者处理,新增处理者灵活,符合开闭原则。
  • 缺点:请求不一定会被处理,如果客户端建立职责链不当,会造成死循环。
  • 适用场景:请求的处理者在运行时才确定,在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。