责任链模式
先来看看什么是责任链模式。
引用一段维基百科对其的解释:
责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。
光看这段描述可能大家会觉得懵,简单来说就是该设计模式用于对某个对象或者请求进行一系列的处理,这些处理逻辑正好组成一个链条。
下面来简单演示使用与不使用责任链模式有什么区别和优势。
责任链模式的应用
传统实现
假设这样的场景:传入了一段内容,需要对这段文本进行加工;比如过滤敏感词、错别字修改、最后署上版权等操作。
常见的写法如下:
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
就是一个典型的责任链模式,它可以让一个请求在整个管道中进行流转。
通过官方图就可以非常清楚的看出是一个责任链模式: