原文:详解Java设计模式之职责链模式_java_脚本之家
责任链模式是一种行为设计模式,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,文中通过代码示例给大家介绍的非常详细,需要的朋友可以参考下
−
目录
职责链模式
1、职责链模式介绍
2、具体例子说明
2.1 不使用职责链模式 - 加薪 / 请假 2.2 职责链模式 - 加薪 / 请假 3、职责链模式总结
职责链模式
1、职责链模式介绍
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系 。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
在责任链模式中,请求通过一条链传递,每个对象都有机会处理请求。当一个对象无法处理请求时,它会将请求传递给链中的下一个对象,直到找到能够处理请求的对象为止 。这种方式可以动态地组织和管理对象,使得请求发送者和接收者之间解耦,提高系统的灵活性和可扩展性。
1.1 职责链模式基本实现
职责链模式结构图:
责任链模式包含以下几个角色:
抽象处理者(Handler):定义了一个处理请求的接口,通常包含一个指向下一个处理者的引用,用于构建责任链。 具体处理者(ConcreteHandler):实现抽象处理者接口,具体处理请求的逻辑。如果可以处理请求,则处理请求;否则,将请求传递给下一个处理者。
Handler类,定义一个处理请示的接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @author Shier
* CreateTime 2023/5/20 16:04
* 处理请求的接口
*/
public
abstract
class
Handler {
protected
Handler successor;
/**
* 设置继承者
* @param successor
*/
public
void
setSuccessor(Handler successor) {
this
.successor = successor;
}
public
abstract
void
handleRequest(
int
request);
}
ConcreteHandler类,具体处理者类,处理它所负责的请求,可访问它的 后继者,如果可处理该请求,就处理之,否则就将该请求转发给它的后继 者。
ConcreteHandler1,当请求数为0~10则有权处理,否则转到下一位:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @author Shier
* CreateTime 2023/5/20 16:06
*/
public
class
ConcreteHandler1
extends
Handler {
@Override
public
void
handleRequest(
int
request) {
if
(request >=
0
&& request <
10
) {
// 当前处理者权限 0 ~ 9
System.out.println(
this
.getClass().getSimpleName() +
"处理了请求"
+ request);
}
else
if
(successor !=
null
) {
// 转移给下一个处理者
successor.handleRequest(request);
}
}
}
ConcreteHandler2,当请求数为10~20则有权处理,否则转到下一位。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @author Shier
* CreateTime 2023/5/20 16:06
*/
public
class
ConcreteHandler2
extends
Handler {
@Override
public
void
handleRequest(
int
request) {
if
(request >=
10
&& request <
20
) {
// 当前处理者权限 10 ~ 19
System.out.println(
this
.getClass().getSimpleName() +
"处理了请求"
+ request);
}
else
if
(successor !=
null
) {
// 转移给下一个处理者
successor.handleRequest(request);
}
}
}
ConcreteHandler3,当请求数为20~99则有权处理,否则转到下一位
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @author Shier
* CreateTime 2023/5/20 16:06
*/
public
class
ConcreteHandler3
extends
Handler {
@Override
public
void
handleRequest(
int
request) {
if
(request >=
20
&& request <
100
) {
// 当前处理者权限 20 ~ 99
System.out.println(
this
.getClass().getSimpleName() +
"处理了请求"
+ request);
}
else
if
(successor !=
null
) {
// 转移给下一个处理者
successor.handleRequest(request);
}
}
}
客户端代码,向链上的具体处理者对象提交请求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @author Shier
* CreateTime 2023/5/20 16:09
*/
public
class
ChainClient {
public
static
void
main(String[] args) {
ConcreteHandler1 handler1 =
new
ConcreteHandler1();
ConcreteHandler2 handler2 =
new
ConcreteHandler2();
ConcreteHandler3 handler3 =
new
ConcreteHandler3();
// 设置职责链上下关系
handler1.setSuccessor(handler2);
handler2.setSuccessor(handler3);
// 请求
int
[] request = {
15
,
67
,
8
,
9
,
46
,
1
,
5
,
23
,
41
};
// 循环给最小矗立着提交请求,不同的数额,得不同的权限处理者处理
for
(
int
i : request) {
handler1.handleRequest(i);
}
}
}
2、具体例子说明
在公司请假或者升职加薪,需要通过经理、总监、总经理的批准,不同身份有不同的权限。当然可以直接直接找总经理给你升职加薪😎
2.1 不使用职责链模式 - 加薪 / 请假
升值加薪:经理是没有权限的,要上报给总监,总监的回复也是没有权限管,只能再上报到总经理才有处理的权限
请假:经理只能处理请假两天的申请,再多就不可以。必须要上报给上司才有权限去处理这个请求。
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
// 申请类
public
class
Request {
// 申请类别
private
String requestType;
public
String getRequestType(){
return
this
.requestType;
}
public
void
setRequestType(String value){
this
.requestType = value;
}
//申请内容
private
String requestContent;
public
String getRequestContent(){
return
this
.requestContent;
}
public
void
setRequestContent(String value){
this
.requestContent = value;
}
// 数量
private
int
number;
public
int
getNumber(){
return
this
.number;
}
public
void
setNumber(
int
value){
this
.number = value;
}
}
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
class
Manager{
protected
String name;
public
Manager(String name){
this
.name = name;
}
public
void
getResult(String managerLevel,Request request){
if
(managerLevel ==
"经理"
){
if
(request.getRequestType()==
"请假"
&& request.getNumber()<=
2
)
System.out.println(
this
.name+
":"
+request.getRequestContent()+
" 数量:"
+request.getNumber()+
"天,被批准"
);
else
System.out.println(
this
.name+
":"
+request.getRequestContent()+
" 数量:"
+request.getNumber()+
"天,我无权处理"
);
}
else
if
(managerLevel ==
"总监"
){
if
(request.getRequestType()==
"请假"
&& request.getNumber()<=
5
)
System.out.println(
this
.name+
":"
+request.getRequestContent()+
" 数量:"
+request.getNumber()+
"天,被批准"
);
else
System.out.println(
this
.name+
":"
+request.getRequestContent()+
" 数量:"
+request.getNumber()+
"天,我无权处理"
);
}
else
if
(managerLevel ==
"总经理"
){
if
(request.getRequestType()==
"请假"
)
System.out.println(
this
.name+
":"
+request.getRequestContent()+
" 数量:"
+request.getNumber()+
"天,被批准"
);
else
if
(request.getRequestType()==
"加薪"
&& request.getNumber()<=
5000
)
System.out.println(
this
.name+
":"
+request.getRequestContent()+
" 数量:"
+request.getNumber()+
"元,被批准"
);
else
if
(request.getRequestType()==
"加薪"
&& request.getNumber()>
5000
)
System.out.println(
this
.name+
":"
+request.getRequestContent()+
" 数量:"
+request.getNumber()+
"元,再说吧"
);
}
}
}
客户端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public
class
Test {
public
static
void
main(String[] args) {
Manager manager =
new
Manager(
"金利"
);
Manager director =
new
Manager(
"宗剑"
);
Manager generalManager =
new
Manager(
"钟精励"
);
Request request =
new
Request();
request.setRequestType(
"加薪"
);
request.setRequestContent(
"Shier请求加薪"
);
request.setNumber(
10000
);
// 不同身份的人有不同的权限,进行处理结果
manager.getResult(
"经理"
, request);
director.getResult(
"总监"
, request);
generalManager.getResult(
"总经理"
, request);
Request request2 =
new
Request();
request2.setRequestType(
"请假"
);
request2.setRequestContent(
"Shier请假"
);
request2.setNumber(
3
);
// 权限级别
manager.getResult(
"经理"
, request2);
director.getResult(
"总监"
, request2);
generalManager.getResult(
"总经理"
, request2);
}
}
通过上面的程序,会发现一个问题管理者类,里面的方法比较长,太多的分支判断。类的责任太多,就违背了单一职责原则,同时增加新的项目时,要去修改这个方法,就违背了开发 - 封闭原则。下面就要用到职责链模式要简化这样开发业务场景 。
2.2 职责链模式 - 加薪 / 请假
将上面的程序进行重构,得到的代码结构图如下:
Request请求类:
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
/**
* @author Shier
* 申请类
*/
public
class
Request {
// 申请类别
private
String requestType;
public
String getRequestType() {
return
this
.requestType;
}
public
void
setRequestType(String value) {
this
.requestType = value;
}
//申请内容
private
String requestContent;
public
String getRequestContent() {
return
this
.requestContent;
}
public
void
setRequestContent(String value) {
this
.requestContent = value;
}
// 数量
private
int
number;
public
int
getNumber() {
return
this
.number;
}
public
void
setNumber(
int
value) {
this
.number = value;
}
}
抽象管理者:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* @author Shier
* CreateTime 2023/5/20 16:33
* 抽象管理这类
*/
public
abstract
class
Manager {
protected
String name;
public
Manager(String name) {
this
.name = name;
}
/**
* 设置管理者上级
*/
protected
Manager superior;
public
void
setSuperior(Manager superior) {
this
.superior = superior;
}
/**
* 请求申请
*
* @param request
*/
public
abstract
void
requestApplications(Request request);
}
经理类就可以去继承这个'管理者'类,只需重写 '申请请求' 的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @author Shier
* CreateTime 2023/5/20 16:34
* 普通经理类
*/
public
class
CommonManager
extends
Manager {
public
CommonManager(String name) {
super
(name);
}
@Override
public
void
requestApplications(Request request) {
if
(request.getRequestType() ==
"请假"
&& request.getNumber() <=
2
) {
System.out.println(
this
.name +
":"
+ request.getRequestContent() +
" 数量:"
+ request.getNumber() +
"天,被批准"
);
}
else
if
(
this
.superior !=
null
) {
this
.superior.requestApplications(request);
}
}
}
总监同样继承抽象管理类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @author Shier
* CreateTime 2023/5/20 16:36
* 总监
*/
public
class
Director
extends
Manager {
public
Director(String name) {
super
(name);
}
@Override
public
void
requestApplications(Request request) {
if
(request.getRequestType() ==
"请假"
&& request.getNumber() <=
5
) {
System.out.println(
this
.name +
":"
+ request.getRequestContent() +
" 数量:"
+ request.getNumber() +
"天,被批准"
);
}
else
if
(
this
.superior !=
null
) {
this
.superior.requestApplications(request);
}
}
}
总经理同样继承管理者类,总经理的权限就是全部都需要处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @author Shier
* CreateTime 2023/5/20 16:36
* 总经理
*/
public
class
GeneralManager
extends
Manager {
public
GeneralManager(String name) {
super
(name);
}
@Override
public
void
requestApplications(Request request) {
if
(request.getRequestType() ==
"请假"
) {
System.out.println(
this
.name +
":"
+ request.getRequestContent() +
" 数量:"
+ request.getNumber() +
"天,被批准"
);
}
else
if
(request.getRequestType() ==
"加薪"
&& request.getNumber() <=
5000
) {
System.out.println(
this
.name +
":"
+ request.getRequestContent() +
" 数量:"
+ request.getNumber() +
"元,被批准"
);
}
else
if
(request.getRequestType() ==
"加薪"
&& request.getNumber() >
5000
) {
System.out.println(
this
.name +
":"
+ request.getRequestContent() +
" 数量:"
+ request.getNumber() +
"元,再说吧"
);
}
}
}
测试类:
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
/**
* @author Shier
*/
public
class
ChainClient {
public
static
void
main(String[] args) {
CommonManager manager =
new
CommonManager(
"大明经理"
);
Director director =
new
Director(
"大大明总监"
);
GeneralManager generalManager =
new
GeneralManager(
"大大大明总经理"
);
// 设置管理者之间上下级关系 经理 => 总监 => 总经理
manager.setSuperior(director);
director.setSuperior(generalManager);
// 加薪 5000
Request request =
new
Request();
request.setRequestType(
"加薪"
);
request.setRequestContent(
"Shier请求加薪"
);
request.setNumber(
5000
);
// 从自己最近的上司开始请求也就是经理
manager.requestApplications(request);
// 加薪10000
Request request1 =
new
Request();
request1.setRequestType(
"加薪"
);
request1.setRequestContent(
"Shier请求加薪"
);
request1.setNumber(
10000
);
manager.requestApplications(request1);
// 请假一天
Request request2 =
new
Request();
request2.setRequestType(
"请假"
);
request2.setRequestContent(
"Shier请假"
);
request2.setNumber(
1
);
manager.requestApplications(request2);
// 请假四天
Request request3 =
new
Request();
request3.setRequestType(
"请假"
);
request3.setRequestContent(
"Shier请假"
);
request3.setNumber(
4
);
manager.requestApplications(request3);
}
}
最后得到的结果:
由于我们把原来的一个 '管理者' 类改成了一个抽象类和三个具体类, 此时类之间的灵活性就大大增加了,如果我们需要扩展新的管理者类别,只需要增加子类就可以。比如这个例子增加一个 '集团总裁' 类,完全是没有问题的,只需要修改 '总经理类' 即可,并不影响其他类代码。
这样使用职责链模式可以更加清晰这些代码之间的关系,不像最上面的一个类里面多个判断语句,看起来都很难维护。好了,再总结一下职责链模式
3、职责链模式总结
职责链模式的好处
当客户提交一个请求时,请求是沿链传递直至有一个 ConcreteHandler 对象负责处理它。 降低耦合:接收者和发送者都没有对方的明确信息,且链中的对 象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅 需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。降低了代码之间耦合度。 灵活性:随时地增加或修改处理一个请求的结构。增强了给对象指派职责的灵活性。
优点:
将请求发送者和接收者解耦,可以避免请求发送者与接收者之间的直接耦合,增强了代码的可维护性。 可以动态地新增或修改请求处理顺序,提高了程序的灵活性和可扩展性。 可以进行请求的拦截、分流 等操作,方便进行统计和日志记录等处理。 可以根据需要对请求的处理进行单独的测试,便于代码测试和调试。 解耦发送者和接收者:职责链模式可以将发送者和接收者解耦,发送者不需要知道请求的具体处理者是谁,而处理者也不需要知道请求的发送者是谁,从而提高系统的灵活性。 动态组合和扩展性:职责链模式允许动态地向链中添加或删除处理者,以适应不同的业务需求,增强了系统的可扩展性。 可配置性:通过调整链中处理者的顺序,可以灵活地配置处理流程,满足不同的处理优先级或条件。
缺点:
请求的保证:没有明确的处理者处理请求的保证。请求可能到达链的末尾而没有被处理,这需要在设计时进行合理的考虑。 性能考虑:由于链中的请求需要依次传递给每个处理者,因此在处理大量请求时可能会影响性能。 可能导致系统变得复杂:当链过长或者处理者过多时,职责链模式可能会导致系统变得复杂,难以理解和维护。
使用场景:
处理复杂的请求处理流程,例如购物车结算、审批流程等复杂业务中。 需要动态指定请求的处理顺序或者动态添加新的请求处理者时。 处理日志记录、缓存等拦截器的场景。例如在Spring中,就应用了责任链模式来实现Interceptor拦截器。 多个对象可以处理同一请求,但具体的处理者在运行时可变或不确定的情况下,可以使用职责链模式。 需要动态组合处理流程或动态调整处理顺序的情况下,职责链模式可以提供灵活性和可配置性。 需要在不明确请求的发送者和接收者之间建立松耦合关系的情况下,职责链模式可以解耦对象之间的关系。
以上就是详解Java设计模式之职责链模式的详细内容,更多关于Java 职责链模式的资料请关注脚本之家其它相关文章!
您可能感兴趣的文章:
深入了解Java设计模式之职责链模式 Java设计模式之职责链模式详解 深入理解Java设计模式之职责链模式 Java职责链模式的深入了解 Java设计模式中单一职责原则详解 Java创建型设计模式之建造者模式详解