什么是责任链模式
解释1:将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
解释2:在职责链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。
二种表现形式
表现形式1:通过链头开始执行,如果不能处理依次往下传递,直到能处理为止
表现形式2:通过链头开始执行 依次传递到联调尾
实现方式一
第一版
//抽象的Handler public abstract class Handler { protected Handler successor = null; public void setSuccessor(Handler successor) { this.successor = successor; } public abstract void handle(); } //链条上的处理器a public class HandlerA extends Handler { @Override public boolean handle() { //标识自己是否能处理 boolean handled = false; //... 省略处理逻辑 处理成功handled改为true //如果不能处理交给下一个handel处理 if (!handled && successor != null) { //交给下一个handle处理 successor.handle(); } } } //联调上的处理器B public class HandlerB extends Handler { @Override public void handle() { //标识自己是否能处理 boolean handled = false; //... 省略处理逻辑 处理成功handled改为true //如果不能处理交给下一个handle处理 if (!handled && successor != null) { successor.handle(); } } } /** * HandlerChain 是处理器链,从数据结构的角度来看,它就是一个记录了链头、链尾的链表。 * 其中,记录链尾是为了方便添加处理器 */ public class HandlerChain { private Handler head = null; private Handler tail = null; public void addHandler(Handler handler) { handler.setSuccessor(null); if (head == null) { head = handler; tail = handler; return; } tail.setSuccessor(handler); tail = handler; } public void handle() { if (head != null) { //从链头依次往下传递 head.handle(); } } } // 使用举例 public class Application { public static void main(String[] args) { //管理链表 HandlerChain chain = new HandlerChain(); //添加处理器 chain.addHandler(new HandlerA()); chain.addHandler(new HandlerB()); //执行处理 chain.handle(); } }
第二版
上面的代码会有问题 如果不熟悉代码结构的人,定义一个handler很容易在handler方法 不能处理漏掉调用下一个处理器, 还有就是上面的handler方法存在重复 所以将调用代码抽象到父类
public abstract class Handler { protected Handler successor = null; public void setSuccessor(Handler successor) { this.successor = successor; } //定义在父类 final修饰不能重写 public final void handle() { //调用 doHanle 由子类实现 模板模式 boolean handled = doHandle(); if (successor != null && !handled) { successor.handle(); } } //抽象的定义 模板模式 protected abstract boolean doHandle(); } public class HandlerA extends Handler { /** * 只关注自身的处理逻辑 * @return */ @Override protected boolean doHandle() { boolean handled = false; //... return handled; } } public class HandlerB extends Handler { /** * 只关注自身的处理逻辑 * @return */ @Override protected boolean doHandle() { boolean handled = false; //... return handled; } } // HandlerChain和Application代码不变
第三版
采用非链表的方式来定义 采用数组的方式 使结构更简单
//定义handler public interface IHandler { boolean handle(); } //处理器a public class HandlerA implements IHandler { @Override public boolean handle() { boolean handled = false; //... return handled; } } //处理器b public class HandlerB implements IHandler { @Override public boolean handle() { boolean handled = false; //... return handled; } } public class HandlerChain { //通过集合维护处理器 private List<IHandler> handlers = new ArrayList<>(); public void addHandler(IHandler handler) { this.handlers.add(handler); } public void handle() { //遍历所有处理器 依次执行 直到其中一个能处理 for (IHandler handler : handlers) { boolean handled = handler.handle(); if (handled) { break; } } } } // 使用举例 public class Application { public static void main(String[] args) { HandlerChain chain = new HandlerChain(); chain.addHandler(new HandlerA()); chain.addHandler(new HandlerB()); chain.handle(); } }
敏感字过滤实战
未使用设计模式
public class SensitiveWordFilter { // return true if content doesn't contain sensitive words. public boolean filter(Content content) { if (!filterSexyWord(content)) { return false; } if (!filterAdsWord(content)) { return false; } if (!filterPoliticalWord(content)) { return false; } return true; } private boolean filterSexyWord(Content content) { //.... } private boolean filterAdsWord(Content content) { //... } private boolean filterPoliticalWord(Content content) { //... } }
缺点 :如果需要增加一种过滤方式 就需要增加一个方法 和增加一个if判断 违反开闭原则
使用了设计模式
//抽象的过滤器 public interface SensitiveWordFilter { boolean doFilter(Content content); } /** * 涉黄过滤 */ public class SexyWordFilter implements SensitiveWordFilter { @Override public boolean doFilter(Content content) { //是否包含敏感字 boolean legal = true; //... return legal; } } // PoliticalWordFilter、AdsWordFilter类代码结构与SexyWordFilter类似 //责任链管理类 public class SensitiveWordFilterChain { private List<SensitiveWordFilter> filters = new ArrayList<>(); public void addFilter(SensitiveWordFilter filter) { this.filters.add(filter); } // return true if content doesn't contain sensitive words. public boolean filter(Content content) { for (SensitiveWordFilter filter : filters) { if (!filter.doFilter(content)) { return false; } } return true; } } public class ApplicationDemo { public static void main(String[] args) { SensitiveWordFilterChain filterChain = new SensitiveWordFilterChain(); filterChain.addFilter(new AdsWordFilter()); filterChain.addFilter(new SexyWordFilter()); filterChain.addFilter(new PoliticalWordFilter()); //传入发表内容 判断是否可发表 boolean legal = filterChain.filter(new Content()); if (!legal) { // 不发表 } else { // 发表 } } }
优点:如果需要增加一种过滤方式 只需要新增一个filter类 注册到chain
源码中的应用
Servlet Filter
它可以实现对 HTTP 请求的过滤功能,比如鉴权、限流、记录日志、验证参数等等。因为它是 Servlet 规范的一部分,所以,只要是支持 Servlet 的 Web 容器(比如,Tomcat、Jetty 等),都支持过滤器功能
具体从ApplicationFilterChain 开始看
Spring MVC拦截器
具体从:HandlerExecutionChain开始看