设计模式——职责链模式

概述

职责链模式:(Chain of Responsibility Pattern)将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。

具体来讲,在职责链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。

何时使用:

  1. 如果有多个对象可以处理同一个请求,但是具体由哪个对象处理是由运行时刻动态决定的,这种对象就可以使用职责链模式,把处理请求的对象实现成职责对象,然后构造链,当请求在这个链中传递的时候,会根据运行状态判断。

  2. 在请求处理者不明确的情况下向多个对象中的一个提交请求。

  3. 需要动态指定处理一个请求的对象集合

UML 类图:

设计模式——职责链模式_第1张图片

角色组成:

  1. 抽象处理者(Handler)角色: 定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handle()规范了子类处理请求的操作。
  2. 具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求2处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

通用代码

Handler.java

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

ConcreteHandlerA.java、ConcreteHandlerB.java

public class ConcreteHandlerA extends Handler {

    @Override
    public boolean doHandle() {
        boolean handled = false;    // 是否已处理
        // ConcreteHandlerA 的处理逻辑
        System.out.println("ConcreteHandlerA 不能处理该请求,继续传递");
        return handled;
    }
}

public class ConcreteHandlerB extends Handler {

    @Override
    public boolean doHandle() {
        boolean handled = false;    // 是否已处理
        // ConcreteHandlerB 的处理逻辑
        System.out.println("ConcreteHandlerB 进行处理");
        return handled;
    }
}

HandlerChain.java

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 Test {
    public static void main(String[] args) {
        HandlerChain chain = new HandlerChain();
        chain.addHandler(new ConcreteHandlerA());
        chain.addHandler(new ConcreteHandlerB());
        chain.handle();
    }
}

结果:

ConcreteHandlerA 不能处理该请求,继续传递
ConcreteHandlerB 进行处理

其中,Handler 是所有处理器类的抽象父类,handle() 是抽象方法。每个具体的处理器类(ConcreteHandlerA、ConcreteHandlerB)的 handle() 函数的代码结构类似,如果它能处理该请求,就不继续往下传递;如果不能处理,则交由后面的处理器来处理(也就是调用 successor.handle())。HandlerChain 是处理器链,从数据结构的角度来看,它就是一个记录了链头、链尾的链表。其中,记录链尾是为了方便添加处理器。

应用场景举例

用户在论坛中发帖内容可能会包含一些敏感词(涉黄、广告、反动等),针对这个应用场景,我们就可以利用职责链模式来过滤这些敏感词。

这些敏感词就是一个个的过滤器,依次去过滤用户发布的内容。

过滤的时候我们有两种处理方式,一种是直接禁止发布,另一种是给敏感词打马赛克之后再发布。第一种处理方式就是上面传统的职责链模式,第二种处理方式是职责链模式的变体。

职责链模式的变体,就是请求会被所有的处理器都处理一遍,不存在中途终止的情况。

总结

职责链模式常用在框架开发中,用来实现框架的过滤器、拦截器功能,让框架的使用者在不需要修改框架源码的情况下,添加新的过滤拦截功能。

Servlet Filter、Spring Interceptor、Tomcat 对 Encoding 的处理都用到了职责链模式。

你可能感兴趣的:(设计模式,java,后端,设计模式,职责链模式)