##责任链模式
责任链是一种行为设计模式,允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。
责任链是由很多责任节点串联起来的一条任务链条,其中每一个责任节点都是一个业务处理环节。责任链模式(Chain ofResponsibility)允许业务请求者将责任链视为一个整体并对其发起请求,而不必关心链条内部具体的业务逻辑与流程走向,也就是说,请求者不必关心具体是哪个节点起了作用,总之业务最终能得到相应的处理。在软件系统中,当一个业务需要经历一系列业务对象去处理时,我们可以把这些业务对象串联起来成为一条业务责任链,请求者可以直接通过访问业务责任链来完成业务的处理,最终实现请求者与响应者的解耦。
责任链模式包括以下几个基本结构:
- 处理者 Handler :定义⼀个处理请求的接⼝,包含⼀个处理请求的抽象⽅法和⼀个指向下⼀个处理者的链
接。
- 具体处理者 ConcreteHandler : 实现处理请求的⽅法,并判断能否处理请求,如果能够处理请求则进行处
理,否则将请求传递给下⼀个处理者。
- 客户端:创建并组装处理者对象链,并将请求发送到链上的第⼀个处理者。

例子
问题:小明所在的公司请假需要在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); }
@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; } }
@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框架中的拦截器,都组装成⼀个处理链对请求、响应进行处理。
优缺点
对比其他模式
- 责任链、命令、中介者和观察者用于处理请求发送者和接收者之间的不同连接方式:
- 责任链按照顺序将请求动态传递给一系列的潜在接收者,直至其中一名接收者对请求进行处理。
- 命令在发送者和请求者之间建立单向连接。
- 中介者清除了发送者和请求者之间的直接连接,强制它们通过一个中介对象进行间接沟通。
- 观察者允许接收者动态地订阅或取消接收请求。
- 责任链通常和组合模式结合使用。在这种情况下,叶组件接收到请求后,可以将请求沿包含全体父组件的链一直传递至对象树的底部。
- 责任链的管理者可使用命令模式实现。在这种情况下,你可以对由请求代表的同一个上下文对象执行许多不同的操作。