一、介绍
责任链模式是把多个对象串联起来形成一个链状结构,让每个对象都有机会对事件发送者的请求进行处理。设计意图是为了使事件发送者和事件接受者之间解耦。责任链模式包含一份请求对象和一系列执行对象,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
是一种处理请求的模式,请求在链上传递。
责任链模式解决的问题:
(1)请求者和接受者松散耦合
在责任链模式中,请求者并不知道接受者是谁,也不知道具体如何处理。请求者只负责向责任链发出请求就可以了,该模式下可以有多个接受者处理对象,每个接受者只负责处理自己的部分,其他的就交给其他的接受者去处理。请求在链中传递,接受者处理该请求,或者传递给链中下一个接受者。请求者不再和特定接受者紧密耦合。
(2)通过改变链内成员的或者调整它们的次序,允许你动态地新增或删除责任。
使用场景:
(1)当一个请求需要根据请求参数的不同由不同对象来处理时候。
(2)当一个请求需要固定对象顺序处理,并且可扩展性的在固定顺序里面插入新的对象进行处理时候。
二、责任链模式示例
2.1、案例1:财务审批
假设某个员工需要报销一笔费用,审核者可以分为:
- Manager:只能审核1000元以下的报销;
- Director:只能审核10000元以下的报销;
- CEO:可以审核任意额度。
用责任链模式设计此报销流程时,每个审核者只关心自己责任范围内的请求,并且处理它。对于超出自己责任范围的,扔给下一个审核者处理,这样,将来继续添加审核者的时候,不用改动现有逻辑。
实现步骤:
(1)抽象出请求对象,它将在责任链上传递
@Data
public class Request {
private String name;
private BigDecimal amount;
}
(2)抽象出处理器
并且做好约定:如果返回Boolean.TRUE
,表示处理成功,如果返回Boolean.FALSE
,表示处理失败(请求被拒绝),如果返回null
,则交由下一个Handler
处理。
public interface Handler {
// 返回Boolean.TRUE = 成功
// 返回Boolean.FALSE = 拒绝
// 返回null = 交下一个处理
Boolean process(Request request);
}
(3)编写具体处理者
依次编写ManagerHandler、DirectorHandler和CEOHandler。以ManagerHandler为例:
public class ManagerHandler implements Handler {
public Boolean process(Request request) {
// 如果超过1000元,处理不了,交下一个处理:
if (request.getAmount().compareTo(BigDecimal.valueOf(1000)) > 0) {
return null;
}
// 对Bob有偏见:
return !request.getName().equalsIgnoreCase("bob");
}
}
(4)有了不同处理者(Handler
)后,还要把这些Handler
组合起来,变成一个链,并通过一个统一入口处理:
public class HandlerChain {
// 持有所有Handler:
private List<Handler> handlers = new ArrayList<>();
public void addHandler(Handler handler) {
this.handlers.add(handler);
}
public boolean process(Request request) {
// 依次调用每个Handler:
for (Handler handler : handlers) {
Boolean r = handler.process(request);
if (r != null) {
// 如果返回TRUE或FALSE,处理结束:
System.out.println(request + " " + (r ? "Approved by " : "Denied by ") + handler.getClass().getSimpleName());
return r;
}
}
throw new RuntimeException("Could not handle request: " + request);
}
}
(5)最后在客户端构造出责任链,然后用责任链来处理请求
// 构造责任链:
HandlerChain chain = new HandlerChain();
chain.addHandler(new ManagerHandler());
chain.addHandler(new DirectorHandler());
chain.addHandler(new CEOHandler());
// 处理请求:
chain.process(new Request("Bob", new BigDecimal("123.45")));
chain.process(new Request("Alice", new BigDecimal("1234.56")));
chain.process(new Request("Bill", new BigDecimal("12345.67")));
chain.process(new Request("John", new BigDecimal("123456.78")));
注意:Handler
添加的顺序很重要,如果顺序不对,处理的结果可能就不是符合要求的。
责任链模式的其余多种场景:
场景1:有些责任链的实现方式是通过某个Handler
手动调用下一个Handler
来传递Request
例如:
public class AHandler implements Handler {
private Handler next;
public void process(Request request) {
if (!canProcess(request)) {
// 手动交给下一个Handler处理:
next.process(request);
} else {
...
}
}
}
场景2:有一些责任链模式,每个Handler
都有机会处理Request
,通常这种责任链被称为拦截器(Interceptor)或者过滤器(Filter),它的目的不是找到某个Handler
处理掉Request
,而是每个Handler
都做一些工作
例如:
- 记录日志;
- 检查权限;
- 准备相关资源;
例如,JavaEE的Servlet规范定义的Filter
就是一种责任链模式,它不但允许每个Filter
都有机会处理请求,还允许每个Filter
决定是否将请求“放行”给下一个Filter
:
public class AuditFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
log(req);
if (check(req)) {
// 放行:
chain.doFilter(req, resp);
} else {
// 拒绝:
sendError(resp);
}
}
}
参考:https://www.liaoxuefeng.com/wiki/1252599548343744/1281319474561057