职责链模式的原理和实现
定义:将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这 些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
在职责链模式中,多个处理器依次处理同一个请 求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。
一个具体的demo如下:
如果它能处理该请求,就不继续往下传递;如果不能处理,则交由后面的处理器来处理(也 就是调用 successor.handle())
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| public abstract class Handler { protected Handler successor = null; public void setSuccessor(Handler successor) { this.successor = successor; } public abstract void handle(); }
public class HandlerA extends Handler { @Override public boolean handle() { boolean handled = false; if (!handled && successor != null) { successor.handle(); } } }
public class HandlerB extends Handler { @Override public void handle() { boolean handled = false; if (!handled && successor != null) { successor.handle(); } } }
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(); } }
|
上述demo存在问题,处理器类的 handle() 函数,不仅包含自己的业务逻 辑,还包含对下一个处理器的调用,也就是代码中的 successor.handle(),如果不熟悉可能会忘记这一步操作,一个优化版本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public abstract class Handler { protected Handler successor = null; public void setSuccessor(Handler successor) { this.successor = successor; } public final void handle() { boolean handled = doHandle(); if (successor != null && !handled) { successor.handle(); } } protected abstract boolean doHandle(); } public class HandlerA extends Handler { @Override protected boolean doHandle() { boolean handled = false; return handled; } } public class HandlerB extends Handler { @Override protected boolean doHandle() { boolean handled = false; return handled; } }
|
职责链模式的应用场景举例
考虑以下场景:我们要设计一个针对于博客或者评论的敏感词过滤模块,就可以使用该模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public interface SensitiveWordFilter { boolean doFilter(Content content); } public class SexyWordFilter implements SensitiveWordFilter { @Override public boolean doFilter(Content content) { boolean legal = true; return legal; } }
public class SensitiveWordFilterChain { private List<SensitiveWordFilter> filters = new ArrayList<>(); public void addFilter(SensitiveWordFilter filter) { this.filters.add(filter); } 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 { } } }
|
其实不使用职责链,而是直接在一个类中使用if else判断也可以完成该功能,那为什么还要使用呢?
1、将大块代码逻辑拆分成函数,将大类拆分成小类,是应对代码复杂性的常用方法。应用职责链模式,把各个敏感词过滤函数继续拆分出来,设计成独立的类,进一步简化了 SensitiveWordFilter 类,让 SensitiveWordFilter 类的代码不会过多,过复杂。
2、如果需要新添加一个过滤方法,我们只需要加一个新的类,实现SensitiveWordFilter接口,并将其添加到SensitiveWordFilterChain中即可,不需要修改太多之前已经存在的代码。如果使用if-else判断的写法,那么就需要添加新的判断。
参考
《设计模式之美》