前言
责任链是一种行为型模式。顾名思义,由多个有不同处理能力节点组成的一条执行链。当一个事件进来时,会判断当前节点是否有处理的能力,反之转入下一个节点进行处理。可以从支付的风控链这个场景,深入的理解责任链模式。
定义
责任链模式:包含了一些命令和一系列的处理对象。每一个处理对象决定了它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。
如何理解
信用卡*,花呗*,白条*,类似的名词对于我们来讲应该不陌生吧。在支付系统中会有一套风控系统,来避免发生类似的事情出现。而风控系统就是责任链模式的一种应用。
比如说给xxx商户配置的风控规则是:
TOP | 信用卡 | 花呗 | 白条 |
---|---|---|---|
木屋烧烤 | 500/日 | 300/日 | 300/日 |
当用户向商家付款时,会根据不同的支付方式,来判断是否触发风控条件。如果达到触发条件则不允许使用该方式支付。来避免发生信用卡*类似的事情。
我们写个简单的风控程序来理解一下:
UML
代码示例
RiskHandler
public abstract class RiskHandler {
/**
* 支付方式
*/
private String payType;
private RiskHandler nextHandler;
public RiskHandler(String payType) {
this.payType = payType;
}
/**
* 是否能支付
* @param order 订单
*/
protected abstract boolean canPay(Order order);
/**
* 处理器
* @param order 订单
* @return 返回true 或者 false
*/
public final boolean handler(Order order){
if(order.getPayType().equals(this.payType)){
return this.canPay(order);
}else {
if (this.nextHandler != null){
return this.nextHandler.handler(order);
}else{
throw new IllegalArgumentException("支付方式有误");
}
}
}
public void setNextHandler(RiskHandler handler){
this.nextHandler = handler;
}
}
CreditHandler
public class CreditHandler extends RiskHandler {
/**
* 500 限额
*/
private BigDecimal limitAmount = BigDecimal.valueOf(500);
public CreditHandler() {
super(PayTypeEnum.CREDIT.getPayType());
}
@Override
protected boolean canPay(Order order) {
if(order.getAmount().compareTo(limitAmount) < 0){
limitAmount = limitAmount.subtract(order.getAmount());
return true;
}else {
return false;
}
}
}
HuabeiHandler
public class HuabeiHandler extends RiskHandler {
/**
* 300 限额
*/
private BigDecimal limitAmount = BigDecimal.valueOf(300);
public HuabeiHandler() {
super(PayTypeEnum.HUA_BEI.getPayType());
}
@Override
protected boolean canPay(Order order) {
if(order.getAmount().compareTo(limitAmount) < 0){
limitAmount = limitAmount.subtract(order.getAmount());
return true;
}else {
return false;
}
}
}
BaiTiaoHandler
public class BaiTiaoHandler extends RiskHandler {
/**
* 300 限额
*/
private BigDecimal limitAmount = BigDecimal.valueOf(300);
public BaiTiaoHandler() {
super(PayTypeEnum.BAI_TIAO.getPayType());
}
@Override
protected boolean canPay(Order order) {
if(order.getAmount().compareTo(limitAmount) < 0){
limitAmount = limitAmount.subtract(order.getAmount());
return true;
}else {
return false;
}
}
}
Order
public interface Order {
/**
* 获取支付方式
* @return 支付方式
*/
String getPayType();
/**
* 获取订单金额
* @return 订单金额
*/
BigDecimal getAmount();
}
ConsumeOrder
public class ConsumeOrder implements Order {
private String payType;
private BigDecimal amount;
public ConsumeOrder(String payType, BigDecimal amount) {
this.payType = payType;
this.amount = amount;
}
@Override
public String getPayType() {
return this.payType;
}
@Override
public BigDecimal getAmount() {
return this.amount;
}
}
PayTypeEnum
public enum PayTypeEnum {
/**
* 花呗
*/
HUA_BEI("hua_bei"),
/**
* 白条
*/
BAI_TIAO("bai_tiao"),
/**
* 信用卡
*/
CREDIT("credit"),
;
private String payType;
PayTypeEnum(String payType) {
this.payType = payType;
}
public String getPayType() {
return payType;
}
}
PayRiskControlService
public class PayRiskControlService {
public boolean canPay(Order order){
// 设置风控
RiskHandler creditHandler = new CreditHandler();
RiskHandler huabeiHandler = new HuabeiHandler();
RiskHandler baiTiaoHandler = new BaiTiaoHandler();
creditHandler.setNextHandler(huabeiHandler);
huabeiHandler.setNextHandler(baiTiaoHandler);
return creditHandler.handler(order);
}
}
Test
public class Test {
public static void main(String[] args) {
// 花呗订单
ConsumeOrder huabeiOrder = new ConsumeOrder(
PayTypeEnum.HUA_BEI.getPayType(), BigDecimal.valueOf(200)
);
// 白条订单
ConsumeOrder baitiaoOrder = new ConsumeOrder(
PayTypeEnum.BAI_TIAO.getPayType(), BigDecimal.valueOf(301)
);
// 加载风控系统
PayRiskControlService riskControlService = new PayRiskControlService();
// 创建订单
boolean canPayOfHuabei = riskControlService.canPay(huabeiOrder);
boolean canPayOfBaitiao = riskControlService.canPay(baitiaoOrder);
System.out.println("canPayOfHuabei = " + canPayOfHuabei);
System.out.println("canPayOfBaitiao = " + canPayOfBaitiao);
}
}
测试结果
ConsumeOrder{payType='hua_bei', amount=200} canPay: true
ConsumeOrder{payType='bai_tiao', amount=301} canPay: false
优点
- 降低耦合度,将请求和处理分开。
- 简化了对象,是对象不需要知道链的结构。
- 增强给对象指派职责的灵活性,通过改变链内的成员或者调动他们的次序,运行动态的新增或者删除责任。
- 增加新的处理类很方便。
缺点
- 不能保证请求一定被接收
- 系统性能将受到一定影响,而且在调试代码时不太方便,可能会造成循环调用。
- 可能不容易观察运行时的特征,有碍于除错。
应用场景
- 有多个对象可以处理同一个请求,具体是哪个对象处理由该请求运行时刻自动确定。
- 在不明确接受者的情况下,向多个对象中的一个提交一个请求。
- 可以动态指定一组对象处理请求。
责任链模式的两种情况
纯的职责链模式
一个请求必须被某一个处理者对象所接收,且一个具体处理者对某个请求的处理只能采用以下两种行为之一:自己处理(承担责任),把责任推给下家处理。
不纯的职责链模式
允许出现某一个具体处理者对象在承担了请求的一部分责任后又将剩余的责任传给下家的情况,且一个请求可以最终不被任何接收端对象所接收。比如说,多级审核,登录安全监测。
注意的点
链中节点数量需要控制,避免出现超长链的情况,一般的做法是在Handler中设置一个最大节点数量,在setNext方法中判断是否已经是超过其阈值,超过则不允许该链建立,避免无意识地破坏系统性能。
参考文章
- 设计模式之禅道第二版
- 责任链设计模式|菜鸟教程
结尾
如果觉得对你有帮助,可以多多评论,多多点赞哦,也可以到我的主页看看,说不定有你喜欢的文章,也可以随手点个关注哦,谢谢。