阅读 144

6月更文挑战|设计模式 —— 责任链模式

这是我参与更文挑战的第9天,活动详情查看:更文挑战

责任链模式

责任链模式是行为型设计模式之一。责任链模式可以理解成单链表结构,每个节点连接着下一个子节点,每个节点支持拆开后重新连接,因此链式结构具备灵活性。这种结构同样适用在设计模式当中,每个节点可以当做是一个对象,每个对象具有处理业务逻辑的能力并且每个对象关联另一个对象。当有一个业务请求从这个链式结构头部开始传递,沿着这条路径依次往下走,根据每个对象处理业务逻辑的能力,当某个对象可以处理该业务请求时把该业务逻辑消费掉,请求也就到此为止,这样一个过程就是责任链模式了。

实现

责任链实现如下,定义一个抽象ACPU类,具备拥有另一个抽象类ACPU的能力。继承ACPU实现CPU1和CPU2,同时实现handleRequest方法处理业务能力。

假设电脑具有多核CPU工作能力,当一个业务逻辑请求输入从CPU1开始传递,当CPU1无法处理该请求时则调用成员对象cpu的handleRequest让它继续处理该业务逻辑,直到有能力的cpu去run这个业务事件。当然一个业务逻辑请求的传递并不一定要从cpu1开始,同样也可以直接调用cpu2处理方法,如果有能力去判断哪个cpu具备处理该事务的能力完全可以越级直接调用。

public abstract class ACPU{
    private ACPU cpu;
    
    public void setCPU(ACPU cpu) {
        this.cpu = cpu;
    }
    public ACPU getCPU() {
        return cpu;
    }
    
    public abstract void handleRequest(String request);
}

public CPU1 extends ACPU{
    @override
    public void handleRequest(String request){
        if(request == "2"){
            if(cpu != null)
            cpu.handleRequest(request);
        }else{
            run();
        }
    }
}

public CPU2 extends ACPU{
    @override
    public void handleRequest(String request){
        if(cpu != null){
            ....
        }else{
            run();
        }
    }
}
CPU1 cpu1 = new CPU1();
CPU2 cpu2 = new CPU2();
cpu1.setCPU(cpu2);
cpu1.handleRequest("2");
cpu1.handleRequest("1");
cpu2.handleRequest("1");
复制代码

实例

OkHttp开源库当中的拦截器就是采用责任链模式。

在interceptors拦截器集合中加入各种类型拦截器,最终传递到RealInterceptorChain。

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

复制代码

RealInterceptorChain是一个拦截器管理器,在遍历拦截器的过程中不断去创建RealInterceptorChain对象去递归处理request, 直至某一个拦截器能够处理该request为止。

public final class RealInterceptorChain implements Interceptor.Chain {

    ......

    public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      RealConnection connection) throws IOException {
        if (index >= interceptors.size()) throw new AssertionError();

        calls++;

        ......

        // Call the next interceptor in the chain.
        RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, 
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout, writeTimeout);
        Interceptor interceptor = interceptors.get(index);
        Response response = interceptor.intercept(next);

        ......
        
        return response;
  }
}
///Interceptor拦截器接口
public interface Interceptor {
  /**
   * 拦截Chain,并触发下一个拦截器的调用
   * @param chain 被处理的对象
   * @return
   * @throws IOException
   */
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    //返回请求
    Request request();
    //对请求进行处理
    Response proceed(Request request) throws IOException;
    ......
  }
}

复制代码

总结

责任链模式似乎又是对if-else形式的优化,优点是从结构上理解其实是将请求者和处理者关系解耦,提高灵活性;缺点也显而易见当责任链的处理者越来越多,链式调用的深度就越大,对于整条链路的遍历反而成为性能影响的原因之一,尤其是对于递归调用函数的使用。

参考

文章分类
阅读
文章标签