阅读 126

DesignPattern - 责任链模式【行为型】

一、责任链模式介绍

责任链模式(Chain of Responsibility Pattern)客户端发出一个请求,链上的对象都有机会来处理这一请求,而客户端不需要知道谁具体的处理对象,让多个对象都有机会处理请求,避免请求的发送者和接收者之间的耦合关系,将这个对象连成一条调用链,并沿着这条链传递该请求,直到有一个对象处理它才终止。

2 个核心行为:一是处理请求,二是将请求传递到下一节点

  • 核心组成

    • Handler 抽象处理者:定义一个处理请求的接口

    • ConcreteHandler 具体处理者:处理所负责的请求,可访问它的后续节点,如果可处理该请求就处理,否则就将该请求转发给它的后续节点

  • 应用场景

    • SprintBoot 里的拦截器、过滤器链

    • Okhttp 里的请求拦截器

    • 在请求处理者不明确的情况下向多个对象中的一个提交请求

    • 如果有多个对象可以处理同一个请求,但是具体由哪个对象处理是由运行时动态决定的,这种对象就可以使用职责链模式

  • 优点

    • 客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递,所以责任链将请求的发送者和请求的处理者降低了耦合度

    • 通过改变链内的调动它们的次序,允许动态地新增或者删除处理类,比较方便维护

    • 增强了系统的可扩展性,可以根据需要增加新的请求处理类,满足开闭原则

    • 每个类只需要处理自己该处理的工作,明确各类的责任范围,满足单一职责原则

  • 缺点

    • 处理都分散到了单独的职责对象中,每个对象功能单一,要把整个流程处理完,需要很多的职责对象,会产生大量的细粒度职责对象

    • 不能保证请求一定被接收,如果链路比较长,系统性能将受到一定影响,而且在进行代码调度时不太方便

二、责任链模式代码实现

以支付宝转账风控为例,根据转账额度不同,会触发的风控级别不一样,1 千以下直接转,1 千到 1 万需要手机号验证码,1 万以上需要刷脸验证。下面使用责任链模式来实现这 3 种风控处理:

创建账号请求类:

/**  * 转账请求  *  * @author GitLqr  */ public class TransferRequest { // 金额 private int money; public TransferRequest(int money) { super(); this.money = money; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } } 复制代码

创建 抽象处理者:

说明:定义一个所有处理者必须实现的处理方法,还需要持有下个处理者的引用

/**  * 抽象处理者:风控抽象类  *  * @author GitLqr  */ public abstract class AbstractRiskControlHandler { // 当前风控处理器名称 protected String name; // 下一级风控处理器 protected AbstractRiskControlHandler superior; public AbstractRiskControlHandler(String name) { super(); this.name = name; } /**  * 处理转账请求  */ public abstract void handleRequest(TransferRequest transferRequest); public AbstractRiskControlHandler getSuperior() { return superior; } public void setSuperior(AbstractRiskControlHandler superior) { this.superior = superior; } } 复制代码

创建 具体处理者:

/**  * 具体处理者:初级风控处理器  *  * @author GitLqr  */ public class FirstRiskControlHandler extends AbstractRiskControlHandler { public FirstRiskControlHandler(String name) { super(name); } @Override public void handleRequest(TransferRequest transferRequest) { if (transferRequest.getMoney() <= 1000) { System.out.println("普通操作,输入支付密码即可"); System.out.println(name + ",转账金额:" + transferRequest.getMoney() + " 处理完成"); } else { // 下个节点进行处理 if (superior != null) { superior.handleRequest(transferRequest); } } } } /**  * 具体处理者:中级风控处理器  *  * @author GitLqr  */ public class SecondRiskControlHandler extends AbstractRiskControlHandler { public SecondRiskControlHandler(String name) { super(name); } @Override public void handleRequest(TransferRequest transferRequest) { if (transferRequest.getMoney() > 1000 && transferRequest.getMoney() <= 10000) { System.out.println("稍大额操作,输入支付密码+短信验证码即可"); System.out.println(name + ",转账金额:" + transferRequest.getMoney() + " 处理完成"); } else { // 下个节点进行处理 if (superior != null) { superior.handleRequest(transferRequest); } } } } /**  * 具体处理者:高级风控处理器  *  * @author GitLqr  */ public class ThirdRiskControlHandler extends AbstractRiskControlHandler { public ThirdRiskControlHandler(String name) { super(name); } @Override public void handleRequest(TransferRequest transferRequest) { if (transferRequest.getMoney() > 10000) { System.out.println("大额操作,输入支付密码+短信验证码+人脸识别"); System.out.println(name + ",转账金额:" + transferRequest.getMoney() + " 处理完成"); } else { // 下个节点进行处理 if (superior != null) { superior.handleRequest(transferRequest); } } } } 复制代码

使用:

public static void main(String[] args) {     AbstractRiskControlHandler firstControlHandler = new FirstRiskControlHandler("初级风控");     AbstractRiskControlHandler secondControlHandler = new SecondRiskControlHandler("中级风控");     AbstractRiskControlHandler thirdControlHandler = new ThirdRiskControlHandler("高级风控");     // 形成调用链     firstControlHandler.setSuperior(secondControlHandler);     secondControlHandler.setSuperior(thirdControlHandler);     TransferRequest request = new TransferRequest(1000); // 1600, 20000     firstControlHandler.handleRequest(request); }


作者:GitLqr
链接:https://juejin.cn/post/7017439694623342623


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐