大话设计模式——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);
    }
}

总结

  • 优点
    • 客户只需要将请求发送到职责链上即可,无需关心请求的具体细节,降低了耦合度
    • 通过改变链内的调动次序,可以动态新增或删除处理类,提高了可维护性
    • 可以根据需求新增请求处理类,提高了可扩展性,同时满足开闭原则
    • 每个请求处理类只服务于自己的责任范围,满足单一职责原则
  • 缺点
    • 要把整个流程走完,可能需要很多的职责对象,可能会造成系统性能降低,同时产生大量的细粒度职责对象,并且出现问题不方便调试
    • 不能保证请求一定被接收
相关推荐
渊渟岳4 小时前
掌握设计模式--装饰模式
设计模式
zh路西法6 小时前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(二):从FSM开始的2D游戏角色操控底层源码编写
c++·游戏·unity·设计模式·状态模式
夏旭泽7 小时前
设计模式-备忘录模式
设计模式·备忘录模式
蓝染-惣右介7 小时前
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
java·设计模式
捕鲸叉11 小时前
C++软件设计模式之类型模式和对象型模式
开发语言·c++·设计模式
诸葛悠闲12 小时前
设计模式——组合模式
设计模式·组合模式
诸葛悠闲12 小时前
设计模式——装饰模式
设计模式
西岭千秋雪_12 小时前
设计模式の中介者&发布订阅&备忘录模式
java·观察者模式·设计模式·中介者模式·备忘录模式
捕鲸叉12 小时前
C++软件设计模式之代理(Proxy)模式
c++·设计模式