责任链模式

40 阅读3分钟

意图

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

用来解耦,客户只要把消息发到责任链上,无需关注请求细节和传递过程

实例

场景:我们在开发应用系统的过程中,经常会遇到记录日志的需求。日志分为三种类型,分别是INFO(消息)、DEBUG(调试) 、ERROR(报错),当需要记录日志的时候,通过判断看看日志属于哪种类型, 然后对应的日志处理类再去处理相应的日志信息。

//抽象的日志记录器类
public abstract class AbstractLogger {

    public static int INFO = 1;
    public static int DEBUG = 2;
    public static int ERROR = 3;

    protected int level;

    /**
     * 责任链中的下一个元素
     */
    protected AbstractLogger nextLogger;

    public void setNextLogger(AbstractLogger nextLogger){
        this.nextLogger = nextLogger;
    }

    public void logMessage(int level, String message){
        if(this.level <= level){
            write(message);
        }
        if(nextLogger !=null){
            nextLogger.logMessage(level, message);
        }
    }
    abstract protected void write(String message);
}
//创建扩展了该记录器类的实体类
class InfoLogger extends AbstractLogger {

    public InfoLogger(int level){
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Info Logger:" + message);
    }
}

class DeBugLogger extends AbstractLogger {

    public DeBugLogger(int level){
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("DeBug Logger:" + message);
    }
}

class ErrorLogger extends AbstractLogger {

    public ErrorLogger(int level){
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Error Logger:" + message);
    }
}
public class Test {

    private static AbstractLogger getChainOfLoggers(){

        AbstractLogger infoLogger = new InfoLogger(AbstractLogger.INFO);
        AbstractLogger deBugLogger = new DeBugLogger(AbstractLogger.DEBUG);
        AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);

        infoLogger.setNextLogger(deBugLogger);
        deBugLogger.setNextLogger(errorLogger);

        return infoLogger;
    }

    public static void main(String[] args) {
        AbstractLogger loggerChain = getChainOfLoggers();

        loggerChain.logMessage(AbstractLogger.INFO, "这是普通日志信息");

        loggerChain.logMessage(AbstractLogger.DEBUG,"这是调试日志信息");

        loggerChain.logMessage(AbstractLogger.ERROR,"这是错误日志信息");
    }
}

运行结果

Task :lib:test.main()
Info Logger:这是普通日志信息
Info Logger:这是调试日志信息
Info Logger:这是调试日志信息
Info Logger:这是错误日志信息
Info Logger:这是错误日志信息
Info Logger:这是错误日志信息

责任链就是想链条一样,一个个传递,也可以在中间增加或减少。
在android中,事件分发机制,父View接到事件,传递给子View。在第三方库okhttp中的拦截器。

//okhttp拦截器源码
Response getResponseWithInterceptorChain() throws IOException {
    //以下通过将所有的连接器加入到集合中
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());   //此处为添加客户端自定义的拦截器

	//其后添加五个内置拦截器
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {   
    //如果没有使用代理连接,添加网络拦截器,也是客户端自定义拦截器
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));

	//创建拦截器链对象,主要用于控制拦截器的顺序执行和各拦截器的加工结果
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);  
 }

优点:

  • 降低耦合度。它将请求的发送者和接收者解耦。
  • 简化了对象。使得对象不需要知道链的结构。
  • 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
  • 增加新的请求处理类很方便。
  • 实现了责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

缺点:

  • 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  • 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
  • 不好调试。