之前,我们说了模板模式,策略模式,现在则是责任链模式,这个模式其本质上也是为了提高代码的复用和扩展,在实际项目开发中比较常用,来定制化框架

在Spring中,Servlet Filter,Spring Interceptor都是用了责任链的设计模式

其定义为,将请求的接收和发送解耦,让多个接受对象都可以有机会进行处理,将这些接收对象串成一个链表,直到链表到头或者某个接收对象接收为止

也就是,一个链表上A-B-C,一个请求过来了,A去处理,没成,B去处理,一直到尽头

链表上每个处理器承担各自的处理职责,这就是职责链模式

常见的实现方式有两种

1.完完全全的按照链表

Handler是所有处理器的父类,然后其中handler是抽象方法,由其中确定,能不能调用

接下来的处理器去处理请求,successor.handler() HandlerChain,是一个链表,也就是处理器链

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();

}

}

但是,上面的方法可以继续进行优化,也就是调用下一个处理器的succesor.handler().导致代码出现了bug,针对这个问题,应该对代码进行重构,将successor.handler()的逻辑从中剥离,根据doHandler()的返回值来进行确定是否调用,重构后的代码如下

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;

}

}

// HandlerChain和Application代码不变

接下来是第二种实现方式,直接使用数组,实现方式更加简单,HandlerChain类使用数组而不是链表保存,这样只需要依次的调用即可

public interface IHandler {

boolean handle();

}

public class HandlerA implements IHandler {

@Override

public boolean handle() {

boolean handled = false;

//…

return handled;

}

}

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();

}

}

利用foreach循环,在某个处理器能够处理的时候,就不会继续往下传递请求,

而真正的责任链模式中,还有一种变体,就是所有的处理器都会进行一次处理,中途不会停止,

也是可以利用链表或者数组来进行存储处理,只需要稍微进行修改就行

我们给出了一种链表的实现方式,其本质就是去掉了判断是否继续执行,依次执行即可

public abstract class Handler {

protected Handler successor = null;

public void setSuccessor(Handler successor) {

this.successor = successor;

}

public final void handle() {

doHandle();

if (successor != null) {

successor.handle();

}

}

protected abstract void doHandle();

}

public class HandlerA extends Handler {

@Override

protected void doHandle() {

//…

}

}

public class HandlerB extends Handler {

@Override

protected void doHandle() {

//…

}

}

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();

}

}

那么,使用职责链模式的场景就很简单了

比如,一个论坛中发表中可能包含一些敏感词,针对这个场景,可以利用职责链模式来进行敏感词过滤,针对过滤词来进行过滤的手段有两种,一种是直接禁止发布,一种是给敏感词打马赛克

这就是分别为拦截处理一次,和依次处理走下去

我们这里给出了第一种的实现方式,我们只给了代码实现的骨架,具体的过滤算法没有给出

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 {

// 发表

}

}

}

但是,有一个问题,如果我们不使用责任链模式,也可以实现这个功能,那么,为什么要是用责任链模式呢?

因为使用责任链模式降低了复杂度,责任链模式将大块逻辑拆分为了小块的,并且拆分为了类,进一步的简化了SensitiveWordFilter类,让其只是一个客户端,不包含具体的代码逻辑

而且更加符合开闭原则,提高了代码的扩展性

当我们修改或者扩展新的过滤算法的时候,我们还要修改调用类的代码,这样违背了开闭员职责,而这责任链的实现方式更加优雅,只需要新添加一个Filter类即可,而且通过addFilter()函数放到FilterChain类中即可

不过细化一下,我们将代码分为两类,分为了客户端代码和框架代码,两者彼此分离,客户端代码只负责调用,不和任何逻辑耦合,框架代码留有扩展点,可以方便扩展

在增加一个新的过滤算法的时候,职责链模式就可以直接添加进去,不需要修改其他的代码

本章总结

责任链模式中,多个处理器处理一个请求,形成了一个链表,让A处理完传给B ,B->C

每个处理器可以只承担自己的处理职责

在定义当中,一旦一个处理器能够处理了,就不传递给后续的处理器了,但是存在着一个变体,中途不会停止传递,而是一直走到尾

而职责链模式有两种常见的实现方式,一种是链表来存储处理器,一种是数组来存储处理器

发表评论

邮箱地址不会被公开。 必填项已用*标注