责任链模式
责任链模式的定义与特点
责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。
标准的责任链模式,个人总结下来有如下几个特点:
- 链上的每个对象都有机会处理请求
- 链上的每个对象都持有下一个要处理对象的引用
- 链上的某个对象无法处理当前请求,那么它会把相同的请求传给下一个对象
纯责任链模式和不纯的责任链模式
如果一个类要么承担责任处理请求要么将请求踢给下一个处理类,则被称为纯责任链模式。
如果一个类承担了一部分责任,还将请求踢给下一个处理类,则被称为不纯的责任链模式。
责任链模式的结构
责任链模式的应用
传统实现
假设这样的场景:传入了一段内容,需要对这段文本进行加工;比如过滤敏感词、错别字修改、最后署上版权等操作。
常见的写法如下:
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)
是无感知的,不需要做任何的改动。
责任链模式的使用场景
1、典型的就是Servlet中的Filter,有了上面的分析,大家应该也可以理解Servlet中责任链模式的工作原理了,然后为什么一个一个的Filter需要配置在web.xml中
2、Netty
中的 pipeline
就是一个典型的责任链模式,它可以让一个请求在整个管道中进行流转。
通过官方图就可以非常清楚的看出是一个责任链模式: