设计模式之责任链模式

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校验
参数合法校验
黑名单校验
相关推荐
reddingtons3 小时前
【游戏宣发】PS “生成式扩展”流,30秒无损适配全渠道KV
游戏·设计模式·新媒体运营·prompt·aigc·教育电商·游戏美术
李慕婉学姐4 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆5 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin6 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20056 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉6 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国6 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882486 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈7 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_997 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc