责任链模式
# 责任链模式
# 定义
责任链模式,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。每个处理器对象都有机会处理请求,也可以选择将请求传递给下一个处理器。
# 结构
抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
- img: https://bitouyun.com/images/design-pattern/resposibility.png
link: https://bitouyun.com/images/design-pattern/resposibility.png
name: 责任链模式
1
2
3
2
3
# 优点
降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
# 缺点
职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
# 应用场景
有多个对象可以处理一个请求,哪个对象处理该请求由运行时刻自动确定。
可动态指定一组对象处理请求,或添加新的处理者。
# 示例代码
场景
公司请假: 1天内需要组长同意;请假3天内需要部门经理同意;请求7天内需要总经理同意。
/**
* 抽象处理者
* 定义了处理请求的接口,并持有下一个处理器的引用,通常包含一个处理方法(如handleRequest()),用于处理请求或将请求传递给下一个处理者。
*/
public abstract class Handler {
protected Handler next;
/**
* 设置下一个处理者
* @param next
*/
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(Leave leave);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 请假实体类
*/
@Data
public class Leave {
// 姓名
private String name;
// 请假天数
private int day;
// 内容
private String content;
public Leave(String name, int day, String content) {
this.name = name;
this.day = day;
this.content = content;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 组长处理者
* 具体处理者,实现了抽象处理者的接口,负责处理特定类型的请求。如果自己无法处理请求,可以将请求传递给下一个处理者。
*/
@Slf4j
public class GroupLeader extends Handler {
@Override
public void handleRequest(Leave leave) {
if (leave.getDay() <= 1) {
log.info("组长:{},请假{}天,批准了.", leave.getName(), leave.getDay());
}else if(next !=null){
next.handleRequest(leave);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 部门经理处理者
* 具体处理者,实现了抽象处理者的接口,负责处理特定类型的请求。如果自己无法处理请求,可以将请求传递给下一个处理者。
*/
@Slf4j
public class DepartmentManager extends Handler {
@Override
public void handleRequest(Leave leave) {
if(leave.getDay()<=3){
log.info("部门经理:{},请假{}天,批准了.", leave.getName(), leave.getDay());
}else if(next !=null) {
next.handleRequest(leave);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 总经理处理者
* 具体处理者,实现了抽象处理者的接口,负责处理特定类型的请求。如果自己无法处理请求,可以将请求传递给下一个处理者。
*/
@Slf4j
public class GeneralManager extends Handler {
@Override
public void handleRequest(Leave leave) {
if (leave.getDay() <= 7) {
log.info("总经理:{}请假{}天,批准了", leave.getName(), leave.getDay());
} else if (next != null) {
next.handleRequest(leave);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 测试类
*/
public class Client {
public static void main(String[] args) {
// 创建处理者对象
Handler groupLeader = new GroupLeader();
DepartmentManager departmentManager = new DepartmentManager();
GeneralManager generalManager = new GeneralManager();
// 设置处理链
groupLeader.setNext(departmentManager);
departmentManager.setNext(generalManager);
// 创建请假请求
Leave zhangSan = new Leave("张三", 1, "郊游");
Leave liSi = new Leave("李四", 3, "省内游");
Leave wangWu = new Leave("王五", 7, "国内游");
// 处理请假请求
groupLeader.handleRequest(zhangSan);
groupLeader.handleRequest(liSi);
groupLeader.handleRequest(wangWu);
}
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Make sure to add code blocks to your code group
上次更新: 2023/11/17, 09:38:49