责任链模式

##责任链模式

责任链是一种行为设计模式,允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。

责任链是由很多责任节点串联起来的一条任务链条,其中每一个责任节点都是一个业务处理环节。责任链模式(Chain ofResponsibility)允许业务请求者将责任链视为一个整体并对其发起请求,而不必关心链条内部具体的业务逻辑与流程走向,也就是说,请求者不必关心具体是哪个节点起了作用,总之业务最终能得到相应的处理。在软件系统中,当一个业务需要经历一系列业务对象去处理时,我们可以把这些业务对象串联起来成为一条业务责任链,请求者可以直接通过访问业务责任链来完成业务的处理,最终实现请求者与响应者的解耦。

责任链模式包括以下几个基本结构:

  1. 处理者 Handler :定义⼀个处理请求的接⼝,包含⼀个处理请求的抽象⽅法和⼀个指向下⼀个处理者的链
    接。
  2. 具体处理者 ConcreteHandler : 实现处理请求的⽅法,并判断能否处理请求,如果能够处理请求则进行处
    理,否则将请求传递给下⼀个处理者。
  3. 客户端:创建并组装处理者对象链,并将请求发送到链上的第⼀个处理者。

image-20240112220044021

例子

问题:小明所在的公司请假需要在OA系统上发布申请,整个请求流程包括多个处理者,每个处理者负责处理不同范围的请假天数,如果一个处理者不能处理请求,就会将请求传递给下一个处理者。审批责任链由主管(Supervisor), 经理(Manager)和董事(Director)组成,他们分别能够处理3天、7天和10天的请假天数。如果超过10天,则进行否决。

处理者

1
2
3
public interface LeaveHandler {
public void handleRequest(LeaveRequest request);
}

具体处理者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Supervisor implements LeaveHandler {
private static final int MAX_DAYS_SUPERVISOR_CAN_APPROVE = 3;
private LeaveHandler nextHandler;

public Supervisor(LeaveHandler nextHandler) {
this.nextHandler = nextHandler;
}

@Override
public void handleRequest(LeaveRequest request) {
if (request.getDays() <= MAX_DAYS_SUPERVISOR_CAN_APPROVE) {
System.out.println(request.getName() + " Approved by Supervisor.");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println(request.getName() + " Denied by Supervisor.");
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Manager implements LeaveHandler {
private static final int MAX_DAYS_MANAGER_CAN_APPROVE = 7;
private LeaveHandler nextHandler;

public Manager(LeaveHandler nextHandler) {
this.nextHandler = nextHandler;
}

@Override

public void handleRequest(LeaveRequest request) {
if (request.getDays() <= MAX_DAYS_MANAGER_CAN_APPROVE) {
System.out.println(request.getName() + " Approved by Manager.");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println(request.getName() + " Denied by Manager.");
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Director implements LeaveHandler {
private static final int MAX_DAYS_DIRECTOR_CAN_APPROVE = 10;
@Override
public void handleRequest(LeaveRequest request) {
if (request.getDays() <= MAX_DAYS_DIRECTOR_CAN_APPROVE) {
System.out.println(request.getName() + " Approved by Director.");
} else {
System.out.println(request.getName() + " Denied by Director.");
}
}

}

请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class LeaveRequest {

private String name;
private int days;

public LeaveRequest(String name, int days) {
this.name = name;
this.days = days;
}

public String getName() {
return name;
}
public int getDays() {
return days;
}
}

Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Main {

public static void main(String[] args) {
// 组装职责链
LeaveHandler director = new Director();
LeaveHandler manager = new Manager(director);
LeaveHandler supervisor = new Supervisor(manager);

//请求
LeaveRequest request1 = new LeaveRequest("Alice" , 2);
LeaveRequest request2 = new LeaveRequest("Bob" , 5);
LeaveRequest request3 = new LeaveRequest("Tom" , 10);
LeaveRequest request4 = new LeaveRequest("Jerry" , 12);

supervisor.handleRequest(request1);
supervisor.handleRequest(request2);
supervisor.handleRequest(request3);
supervisor.handleRequest(request4);
}
}


Alice Approved by Supervisor.
Bob Approved by Manager.
Tom Approved by Director.
Jerry Denied by Director.

Spring依赖注入实现

责任链处理器

handlerList会按照Order的优先级进行排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Component
public class HandlerManager implements ApplicationContextAware {
private List<RequestHandler> handlerList;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
handlerList = applicationContext.getBeansOfType(RequestHandler.class).values().stream()
.sorted()
.collect(Collectors.toList());
}

public void handleRequest(Request request) {
for (RequestHandler handler : handlerList) {
try {
handler.handleRequest(request);
break; // 一旦请求被处理,就中断循环
} catch (UnsupportedOperationException e) {
// 当前处理器不支持处理该请求,继续下一个
}
}
}
}

使用Order注解确定处理器

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
// 请求处理接口
public interface RequestHandler extends Ordered {
void handleRequest(Request request);
}

// 具体处理者1
@Order(1) // 指定处理顺序
public class ConcreteHandler1 implements RequestHandler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE1) {
System.out.println("ConcreteHandler1 handles this request");
} else {
throw new UnsupportedOperationException("ConcreteHandler1 cannot handle this request");
}
}

@Override
public int getOrder() {
return 1; // 返回顺序值,数值越小优先级越高
}
}

// 具体处理者2
@Order(2)
public class ConcreteHandler2 implements RequestHandler {
@Override
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE2) {
System.out.println("ConcreteHandler2 handles this request");
} else {
throw new UnsupportedOperationException("ConcreteHandler2 cannot handle this request");
}
}

@Override
public int getOrder() {
return 2;
}
}

使用场景

责任链模式是设计模式中简单且常见的设计模式,在日常中也会经常使⽤到,比如Java开发中过滤器的链式处理,
以及Spring框架中的拦截器,都组装成⼀个处理链对请求、响应进行处理。

优缺点

  • 可以控制请求处理的顺序。

  • 单一职责原则。你可对发起操作和执行操作的类进行解耦。

  • 开闭原则。你可以在不更改现有代码的情况下在程序中新增处理者。

  • 部分请求可能未被处理。

  • deBug可能会比较困难。

对比其他模式

  • 责任链、命令、中介者和观察者用于处理请求发送者和接收者之间的不同连接方式:
    • 责任链按照顺序将请求动态传递给一系列的潜在接收者,直至其中一名接收者对请求进行处理。
    • 命令在发送者和请求者之间建立单向连接。
    • 中介者清除了发送者和请求者之间的直接连接,强制它们通过一个中介对象进行间接沟通。
    • 观察者允许接收者动态地订阅或取消接收请求。
  • 责任链通常和组合模式结合使用。在这种情况下,叶组件接收到请求后,可以将请求沿包含全体父组件的链一直传递至对象树的底部。
  • 责任链的管理者可使用命令模式实现。在这种情况下,你可以对由请求代表的同一个上下文对象执行许多不同的操作。

责任链模式
http://example.com/2023/10/15/计算机基础/设计模式/21-责任链模式/
作者
PALE13
发布于
2023年10月15日
许可协议