利用责任链模式设计一个拦截器(上)

简介: 近期在做 Cicada 的拦截器功能,正好用到了责任链模式。这个设计模式在日常使用中频率还是挺高的,借此机会来分析分析。

责任链模式


先来看看什么是责任链模式。


引用一段维基百科对其的解释:


责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。


光看这段描述可能大家会觉得懵,简单来说就是该设计模式用于对某个对象或者请求进行一系列的处理,这些处理逻辑正好组成一个链条。


下面来简单演示使用与不使用责任链模式有什么区别和优势。


责任链模式的应用


传统实现


假设这样的场景:传入了一段内容,需要对这段文本进行加工;比如过滤敏感词、错别字修改、最后署上版权等操作。


常见的写法如下:


public class Main {
    public static void main(String[] args) {
        String msg = "内容内容内容" ;
        String result = Process.sensitiveWord()
                .typo()
                .copyright();
    }
}


这样看似没啥问题也能解决需求,但如果我还需要为为内容加上一个统一的标题呢?在现有的方式下就不得不新增处理方法,并且是在这个客户端(Process)的基础上进行新增。


显然这样的扩展性不好。


责任链模式实现


这时候就到了责任链模式发挥作用了。


该需求非常的符合对某一个对象、请求进行一系列处理的特征。


于是我们将代码修改:


这时 Process 就是一个接口了,用于定义真正的处理函数。


public interface Process {
    /**
     * 执行处理
     * @param msg
     */
    void doProcess(String msg) ;
}


同时之前对内容的各种处理只需要实现该接口即可:


public class SensitiveWordProcess implements Process {
    @Override
    public void doProcess(String msg) {
        System.out.println(msg + "敏感词处理");
    }
}
public class CopyrightProcess implements Process {
    @Override
    public void doProcess(String msg) {
        System.out.println(msg + "版权处理");
    }
}
public class CopyrightProcess implements Process {
    @Override
    public void doProcess(String msg) {
        System.out.println(msg + "版权处理");
    }
}


然后只需要给客户端提供一个执行入口以及添加责任链的入口即可:


public class MsgProcessChain {
    private List<Process> chains = new ArrayList<>() ;
    /**
     * 添加责任链
     * @param process
     * @return
     */
    public MsgProcessChain addChain(Process process){
        chains.add(process) ;
        return this ;
    }
    /**
     * 执行处理
     * @param msg
     */
    public void process(String msg){
        for (Process chain : chains) {
            chain.doProcess(msg);
        }
    }
}


这样使用起来就非常简单:


public class Main {
    public static void main(String[] args) {
        String msg = "内容内容内容==" ;
        MsgProcessChain chain = new MsgProcessChain()
                .addChain(new SensitiveWordProcess())
                .addChain(new TypoProcess())
                .addChain(new CopyrightProcess()) ;
        chain.process(msg) ;
    }
}


当我需要再增加一个处理逻辑时只需要添加一个处理单元即可(addChain(Process process)),并对客户端 chain.process(msg) 是无感知的,不需要做任何的改动。


可能大家没有直接写过责任链模式的相关代码,但不经意间使用到的却不少。


比如 Netty 中的 pipeline 就是一个典型的责任链模式,它可以让一个请求在整个管道中进行流转。



通过官方图就可以非常清楚的看出是一个责任链模式:


相关文章
|
4月前
|
设计模式
|
6月前
|
设计模式 JavaScript 前端开发
如何优雅的使用责任链模式?
【6月更文挑战第7天】如何优雅的使用责任链模式?
|
7月前
|
设计模式
职责链模式
职责链模式
49 0
|
7月前
|
设计模式 PHP
php设计模式--责任链模式(五)
php设计模式--责任链模式(五)
38 0
|
JavaScript 测试技术
关于责任链模式我所知道的
关于责任链模式我所知道的
87 0
|
设计模式 数据处理
我学会了,职责链模式
职责链模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。
118 0
我学会了,职责链模式
责任链模式简单介绍
责任链模式简单介绍
140 0
|
设计模式 前端开发
利用责任链模式设计一个拦截器(下)
近期在做 Cicada 的拦截器功能,正好用到了责任链模式。 这个设计模式在日常使用中频率还是挺高的,借此机会来分析分析。
|
Java Nacos Sentinel
责任链模式详解(上)
责任链模式详解
239 0
责任链模式详解(上)
|
设计模式 XML 数据格式