简介
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
主要有两个核心行为:1.处理请求;2.将请求传递到下一节点
UML图:
应用场景
- Apache Tomcat 对 Encoding 编码的处理,Springboot 中的拦截器和过滤器链
- 存在多个对象可以处理同一个请求,但具体哪个请求进行处理由运行时动态决定
- 日志级别:debugger -> info -> warning -> error
示例
金融行业的一些风控规则,受限于一些政策会经常进行调整,不同的交易金额有不同的风控策略进行处理
- Client:
public class Request {/*** 金额*/private double money;/*** 请求类型*/private String requestType;public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}public String getRequestType() {return requestType;}public void setRequestType(String requestType) {this.requestType = requestType;}
}
- Handler:
public abstract class RiskManager {/*** 防控策略*/protected String riskName;/*** 上级防控*/protected RiskManager superior;public RiskManager(String riskName) {this.riskName = riskName;}/*** 处理请求** @param request*/public abstract void handleRequest(Request request);public RiskManager getSuperior() {return superior;}public void setSuperior(RiskManager superior) {this.superior = superior;}
}
一级防控:
public class FirstRiskManager extends RiskManager {public FirstRiskManager(String riskName) {super(riskName);}@Overridepublic void handleRequest(Request request) {if ("线上".equals(request.getRequestType()) && 2000 > request.getMoney()) {System.out.println("支付方式:" + request.getRequestType() + ",支付金额:" + request.getMoney() + ",防控策略:" + riskName);} else {if (null != superior) {// 触发其他防控策略superior.handleRequest(request);}}}
}
二级防控:
public class SecondRiskManager extends RiskManager {public SecondRiskManager(String riskName) {super(riskName);}@Overridepublic void handleRequest(Request request) {if ("线上".equals(request.getRequestType()) && 5000 > request.getMoney()) {System.out.println("支付方式:" + request.getRequestType() + ",支付金额:" + request.getMoney() + ",防控策略:" + riskName);} else {System.out.println("支付方式:" + request.getRequestType() + ",支付金额:" + request.getMoney() + ",防控策略:限制交易!");}}
}
- 运行
public class Main {public static void main(String[] args) {FirstRiskManager firstRiskManager = new FirstRiskManager("一级防控,正常交易");SecondRiskManager secondRiskManager = new SecondRiskManager("二级防控,重点监控");firstRiskManager.setSuperior(secondRiskManager);Request request = new Request();request.setRequestType("线上");// 一级防控request.setMoney(1200);firstRiskManager.handleRequest(request);// 二级防控request.setMoney(4000);firstRiskManager.handleRequest(request);// 最终防控request.setMoney(6000);firstRiskManager.handleRequest(request);}
}
总结
- 优点
- 客户只需要将请求发送到职责链上即可,无需关心请求的具体细节,降低了耦合度
- 通过改变链内的调动次序,可以动态新增或删除处理类,提高了可维护性
- 可以根据需求新增请求处理类,提高了可扩展性,同时满足开闭原则
- 每个请求处理类只服务于自己的责任范围,满足单一职责原则
- 缺点
- 要把整个流程走完,可能需要很多的职责对象,可能会造成系统性能降低,同时产生大量的细粒度职责对象,并且出现问题不方便调试
- 不能保证请求一定被接收