责任链设计模式(Chain of Responsibility Pattern)
- 客户端发出一个请求,链上的对象都有机会来处理这一请求,而客户端不需要知道谁是具体的处理对象
- 让多个对象都有机会处理请求,避免请求的发送者和接收者之间的耦合关系,将这个对象连成一条调用链,并沿着这条链传递该请求,直到有一个对象处理它才终止
- 有两个核心行为:一是处理请求,二是将请求传递到下一节点
应用场景
- Apache Tomcat对Encoding编码处理的处理,SpringBoot里面的拦截器、过滤器链
- 在请求处理者不明确的情况下向多个对象中的一个提交请求
- 如果有多个对象可以处理同一个请求,但是具体由哪个对象处理是由运行时刻动态决定的,这种对象就可以使用责任链模式
角色
Handler抽象处理者:定义了一个处理请求的接口
ConcreterHandler具体处理者 :处理所负责的请求,可访问它的后续节点,如果可处理该请求就处理,否则就将该请求转发给它的后续节点
代码示例,以转账风控为例
/** * 风控级别抽象类 */ abstract class RiskControlManager { /** * 名称 */ protected String name; /** * 更严格的风控策略 */ protected RiskControlManager superior; public RiskControlManager(String name) { this.name = name; } /** * 设置更严格的风控策略 * * @param superior */ public void setSuperior(RiskControlManager superior) { this.superior = superior; } /** * 处理请求 * * @param money */ public abstract void handlerRequest(double money); } /** * 一级风控,只处理3000元以内的 */ class FirstRiskControlManager extends RiskControlManager { public FirstRiskControlManager(String name) { super(name); } @Override public void handlerRequest(double money) { if (money <= 3000) { System.out.println(name + "3000元以内的为普通支付,输入支付密码即可,该金额为:" + money); } else { // 下个节点进行处理 if (superior != null) { superior.handlerRequest(money); } } } } /** * 二级风控,超过3000元的处理 */ class SecondRiskControlManager extends RiskControlManager { public SecondRiskControlManager(String name) { super(name); } @Override public void handlerRequest(double money) { if (money > 3000) { System.out.println(name + "超过3000元,需要人脸识别,该金额为:" + money); } else { // 下个节点进行处理 if (superior != null) { superior.handlerRequest(money); } } } } public class Main { public static void main(String[] args) { FirstRiskControlManager firstRiskControlManager = new FirstRiskControlManager("一级风控"); SecondRiskControlManager secondRiskControlManager = new SecondRiskControlManager("二级风控"); // 形成调用链 firstRiskControlManager.setSuperior(secondRiskControlManager); // 使用 firstRiskControlManager.handlerRequest(11500); } }
优点
- 客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者降低了耦合度
- 通过改变链内的调动它们的次序,允许动态的新增或者删除处理类,比较方便维护
- 增强了系统的可扩展性,可以根据需要增加新的请求处理类,满足开闭原则
- 每个类只需要处理自己该处理的工作,明确各类的责任范围,满足单一职责原则
缺点
- 处理都分散到了单独的职责对象中,每个对象功能单一,要把整个流程处理完,需要很多的职责对象,会产生大量的细粒度职责对象
- 不能保证请求一定被接收
- 如果链路太长,系统性能将受到一定影响,而且在进行代码调试时不太方便
日志处理级别
- debug–>info–>warn–>error