一、什么是责任链模式模式(Chain of Responsibility)
- 客户端发出一个请求,链上的对象都有机会来处理这一请求,而客户端不需要知道谁是具体的处理对象。
- 让多个对象都有机会处理请求,避免请求的发送者和接收者之间的耦合关系,将这个对象连成一条调用链,并沿着这条链传递该请求,直到有一个对象处理它才终止。
- 有两个核心行为:一是处理请求,二是将请求传递到下—节点。
业务需求场景: 风控规则,根据每个场景,定义一些规则。 使用中的案例
二、责任链模式的实现方式
模式结构分析:
- Handler抽象处理者:定义了一个处理请求的接口。获取它的后续节点。
- ConcreteHandler具体处理者:处理所负责的请求,可访问它的后续节点,如果可处理该请求就处理,否则就将该请求转发给它的后续节点。
类关系图:
统一模型:
代码实现:
查看代码
@Data
public class ChainRequest {
//类别
String requestType;
//⾦额
int money;
}
public enum RequestTypeEnum {
/**
* 转账
*/
TRANSFER,
/**
* 提现
*/
CASH_OUT;
}
/*
* ⻛控级别抽象类
* */
public 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 request
*/
public abstract void handlerRequest(ChainRequest request);
}
public class FirstRiskControlManager extends RiskControlManager {
public FirstRiskControlManager(String name) {
super(name);
}
@Override
public void handlerRequest(ChainRequest request) {
if (RequestTypeEnum.valueOf(request.getRequestType()) != null && request.getMoney() <= 1000) {
System.out.println("普通操作,输⼊⽀付 密码即可");
System.out.println(name + ":" + request.getRequestType() + ", ⾦额:" + request.getMoney() + " 处理完成");
} else {
//下个节点进⾏处理
if (superior != null) {
superior.handlerRequest(request);
}
}
}
}
public class SecondRiskControlManager extends RiskControlManager {
public SecondRiskControlManager(String name) {
super(name);
}
@Override
public void handlerRequest(ChainRequest request) {
if (RequestTypeEnum.valueOf(request.getRequestType())!=null && request.getMoney()>1000 &&request.getMoney()<10000) {
System.out.println("稍大额操作,输入付密码+短信验证码即可");
System.out.println(name+":"+request.getRequestType() + ", ?额:"+request.getMoney() +" 处理完成");
} else {
//下个节点进⾏处理
if (superior != null) {
superior.handlerRequest(request);
}
}
}
}
public class ThirdRiskControlManager extends RiskControlManager {
public ThirdRiskControlManager(String name) {
super(name);
}
@Override
public void handlerRequest(ChainRequest request) {
if (RequestTypeEnum.valueOf(request.getRequestType()) != null && request.getMoney()>10000) {
System.out.println("⼤额操作,输⼊⽀付 密码+验证码+⼈脸识别");
System.out.println(name + ":" + request.getRequestType() + ", ⾦额:" + request.getMoney() + " 处理完成");
} else {
//下个节点进⾏处理
if (superior != null) {
superior.handlerRequest(request);
}
}
}
}
/*
* 风险责任链
* */
public class RiskChainContext {
public RiskControlManager getRiskContext(){
RiskControlManager firstControlManager = new FirstRiskControlManager("初级⻛控");
RiskControlManager secondControlManager = new SecondRiskControlManager("中级⻛控");
RiskControlManager thirdControlManager = new ThirdRiskControlManager("⾼级⻛控");
//形成调⽤链
firstControlManager.setSuperior(secondControlManager);
secondControlManager.setSuperior(thirdControlManager);
return firstControlManager;
}
}
测试用例:
/*
* 责任链模式
* */
@Test
public void getChainOfResponsibility(){
RiskChainContext riskChainContext=new RiskChainContext();
RiskControlManager firstControlManager =riskChainContext.getRiskContext();
//使⽤
ChainRequest request1 = new ChainRequest();
request1.setRequestType(RequestTypeEnum.CASH_OUT.name());
request1.setMoney(20000);
firstControlManager.handlerRequest(request1);
}
测试结果:
⼤额操作,输⼊⽀付 密码+验证码+⼈脸识别
⾼级⻛控:CASH_OUT, ⾦额:20000 处理完成
方法评估:
优点:
- 客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者降低了耦合度
- 通过改变链内的调动它们的次序,允许动态地新增或者删除处理类,比较很方便维护
- 增强了系统的可扩展性,可以根据需要增加新的请求处理类,满足开闭原则
- 每个类只需要处理自己该处理的工作,明确各类的责任范围,满足单一职责原则
缺点:
- 处理都分散到了单独的职责对象中,每个对象功能单一,要把整个流程处理完,需要很多的职责对象,会产生大量的细粒度职责对象
- 不能保证请求一定被接收;
- 如果链路比较长,系统性能将受到一定影响,而且在进行代码调试时不太方便