设计模式之责任链模式

1. 责任链模式

1.1 责任链模式定义

当你想要让一个以上的对象 有机会能够处理某个请求的时候,就使用责任链模式

责任链模式为请求创建了一个接收者对象的链。执行链上有多个对象节点,每个对象节点都有机会(条件匹配)处理请求事务,如果某个对象节点处理完了,就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。

关键点

  • 解耦:请求的发送者不需要知道谁会处理这个请求,也不需要知道处理请求的具体过程。
  • 灵活性:可以在运行时动态地改变处理者链,使得系统更加灵活。
  • 可扩展性:可以轻松地向现有系统中添加新的处理者,而无需修改现有的代码。

结构

  • 抽象处理者(Handler) :定义了一个处理请求的接口,并且有一个指向其后续处理者的引用。

    具体处理者(Concrete Handler):实现抽象处理者的接口,根据实际情况决定是否处理请求或将其转发给下一个处理者。

  • 具体处理者(Concrete Handler):实现抽象处理者的接口,根据实际情况决定是否处理请求或将其转发给下一个处理者。

  • 客户端(Client):创建一个处理者链,并将请求提交给第一个处理者。

Spring AOP、Spring事务管理的一个重要特性是它使用了责任链模式;Spring MVC中的拦截器(Interceptor)等都用到了责任链模式。

1.2 责任链模式使用

责任链模式怎么使用呢?

  • 一个接口或者抽象类
  • 每个对象差异化处理
  • 对象链(数组)初始化(连起来)

1.3 具体代码

首先创建一个接口或者抽象类
java 复制代码
public abstract class AbstractHandler {

    /**
     * 责任链中的下一个对象
     */
    private AbstractHandler nextHandler;

    /**
     * 责任链的下一个对象
     */
    public void setNextHandler(AbstractHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    /**
     * 具体参数拦截逻辑,给子类去实现
     */
    public void filter(HttpServletRequest request, HttpServletResponse response) {
        doFilter(request, response);
        if (getNextHandler() != null) {
            getNextHandler().filter(request, response);
        }
    }

    public AbstractHandler getNextHandler() {
        return nextHandler;
    }

    /**
     * 抽象方法
     * @param filterRequest
     * @param response
     */
    abstract void doFilter(HttpServletRequest filterRequest, HttpServletResponse response);

}
每个对象差异化处理
java 复制代码
@Component
@Order(1)
public class CheckRequestHeaderFilterObject extends AbstractHandler {
    @Override
    void doFilter(HttpServletRequest filterRequest, HttpServletResponse response) {
        System.out.println("请求头校验");
    }
}
java 复制代码
@Component
@Order(2)
public class CheckCorsFilterObject extends AbstractHandler{
    @Override
    void doFilter(HttpServletRequest filterRequest, HttpServletResponse response) {
        System.out.println("cors校验");
    }
}
java 复制代码
@Component
@Order(3)
public class CheckParamFilterObject extends AbstractHandler{
    @Override
    void doFilter(HttpServletRequest filterRequest, HttpServletResponse response) {
        System.out.println("参数合法校验");
    }
}
java 复制代码
@Component
@Order(4)
public class CheckBlackFilterObject extends AbstractHandler{
    @Override
    void doFilter(HttpServletRequest filterRequest, HttpServletResponse response) {
        System.out.println("黑名单校验");
    }
}
对象链连起来(初始化)&& 使用
java 复制代码
@Component("ChainPatternTest")
public class ChainPatternTest {

    /**
     * 自动注入各个责任链的对象
     */
    @Resource
    private List<AbstractHandler> abstractHandleList;

    private AbstractHandler abstractHandler;

    /**
     * spring注入后自动执行,责任链的对象连接起来
     */
    @PostConstruct
    public void initializeChainFilter() {
        for (int i = 0; i < abstractHandleList.size(); i++) {
            if (i == 0) {
                abstractHandler = abstractHandleList.get(0);
            } else {
                AbstractHandler currentHandler = abstractHandleList.get(i - 1);
                AbstractHandler nextHandler = abstractHandleList.get(i);
                currentHandler.setNextHandler(nextHandler);
            }
        }
    }

    /**
     * 直接调用这个方法使用,根据实际使用来返回数据内容等
     *
     * @param request
     * @param response
     * @return
     */
    public HttpServletResponse exec(HttpServletRequest request, HttpServletResponse response) {
        abstractHandler.filter(request, response);
        return response;
    }

    public AbstractHandler getAbstractHandler() {
        return abstractHandler;
    }

    public void setAbstractHandler(AbstractHandler abstractHandler) {
        this.abstractHandler = abstractHandler;
    }
}

调用运行结果如下:

json 复制代码
请求头校验
cors校验
参数合法校验
黑名单校验
相关推荐
大葱白菜9 分钟前
Java Set 集合详解:从基础语法到实战应用,彻底掌握去重与唯一性集合
java·后端
大葱白菜10 分钟前
Java Map 集合详解:从基础语法到实战应用,彻底掌握键值对数据结构
java·后端
添乱10 分钟前
「Java案例」判断是否是闰年的方法
java
FG.14 分钟前
Day22
java·面试
菜鸟的迷茫16 分钟前
Redis 缓存雪崩、穿透、击穿面试题深度解析与 Spring Boot 实战代码示例
java
珹洺27 分钟前
C++算法竞赛篇:DevC++ 如何进行debug调试
java·c++·算法
SHUIPING_YANG35 分钟前
根据用户id自动切换表查询
java·服务器·数据库
爱吃烤鸡翅的酸菜鱼1 小时前
IDEA高效开发:Database Navigator插件安装与核心使用指南
java·开发语言·数据库·编辑器·intellij-idea·database
惊涛骇浪、1 小时前
SpringMVC + Tomcat10
java·tomcat·springmvc
墨染点香1 小时前
LeetCode Hot100【6. Z 字形变换】
java·算法·leetcode