大话设计模式——19.责任链模式(Chain of Responsibility Pattern)

简介

使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

主要有两个核心行为:1.处理请求;2.将请求传递到下一节点

UML图:
应用场景
  • Apache Tomcat 对 Encoding 编码的处理,Springboot 中的拦截器和过滤器链
  • 存在多个对象可以处理同一个请求,但具体哪个请求进行处理由运行时动态决定
  • 日志级别:debugger -> info -> warning -> error

示例

金融行业的一些风控规则,受限于一些政策会经常进行调整,不同的交易金额有不同的风控策略进行处理

  1. Client:
java 复制代码
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;
    }
}
  1. Handler:
java 复制代码
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;
    }
}

一级防控:

java 复制代码
public class FirstRiskManager extends RiskManager {

    public FirstRiskManager(String riskName) {
        super(riskName);
    }

    @Override
    public 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);
            }
        }
    }
}

二级防控:

java 复制代码
public class SecondRiskManager extends RiskManager {

    public SecondRiskManager(String riskName) {
        super(riskName);
    }

    @Override
    public 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() + ",防控策略:限制交易!");
        }
    }
}
  1. 运行
java 复制代码
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);
    }
}

总结

  • 优点
    • 客户只需要将请求发送到职责链上即可,无需关心请求的具体细节,降低了耦合度
    • 通过改变链内的调动次序,可以动态新增或删除处理类,提高了可维护性
    • 可以根据需求新增请求处理类,提高了可扩展性,同时满足开闭原则
    • 每个请求处理类只服务于自己的责任范围,满足单一职责原则
  • 缺点
    • 要把整个流程走完,可能需要很多的职责对象,可能会造成系统性能降低,同时产生大量的细粒度职责对象,并且出现问题不方便调试
    • 不能保证请求一定被接收
相关推荐
vker2 小时前
第 1 天:单例模式(Singleton Pattern)—— 创建型模式
java·设计模式
晨米酱20 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机1 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机1 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤1 天前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机2 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴2 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript