首页 > 其他分享 >重修设计模式-行为型-责任链模式

重修设计模式-行为型-责任链模式

时间:2024-09-26 18:55:08浏览次数:10  
标签:... 拦截器 handle handled 重修 interceptors 责任 处理器 设计模式

重修设计模式-行为型-责任链模式

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

责任链模式(Chain of Responsibility Pattern)也叫职责链模式,通过将请求的处理分配给一系列的处理对象,这些处理对象通过链式结构组织起来,以实现对请求的灵活处理。比如,一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条,链条上的每个处理器承担各自的处理职责。

责任链模式的原理非常简单,有两种常用的实现。一种是使用链表来存储处理器,另一种是使用数组来存储处理器,后面一种实现方式更加简单。

1.链表方式

使用链表结构存储处理器,如果有处理器能处理该请求,就不继续往下传递;如果不能处理,则交由后面的处理器来处理。

//处理器
abstract class Handler {
    var next: Handler? = null

    abstract fun handle()
}

class Handler1: Handler() {
    override fun handle() {
        var handled = false
        //doAction...
        handled = Random.nextBoolean()
        println("${javaClass.simpleName}处理逻辑... 处理结果:$handled")
        //...
        if (!handled && next != null) {  //如果处理不了,交给下一个处理器
            next?.handle()
        }
    }
}

class Handler2: Handler() {
    override fun handle() {
        var handled = false
        //doAction...
        handled = Random.nextBoolean()
        println("${javaClass.simpleName}处理逻辑... 处理结果:$handled")
        //...
        if (!handled && next != null) {
            next?.handle()
        }
    }
}


//处理器链
class HandlerChain {
    var head: Handler? = null
    var tail: Handler? = null

    fun addHandle(handler: Handler) {
        handler.next = null
        if (head == null) {
            head = handler
            tail = handler
            return
        }
        tail?.next = handler
        tail = handler
    }

    fun handle() {
        head?.handle()
    }
}

//使用时:
fun main() {
    val chain = HandlerChain()
    chain.addHandle(Handler1())
    chain.addHandle(Handler2())
    chain.handle()  //开始责任链调用
}

2.集合方式

使用集合存储所有处理器,调用时通过遍历来串联所有处理器,实现更加简单

//处理器
abstract class HandlerList {
    abstract fun handle(): Boolean
}

class HandlerA : HandlerList() {
    override fun handle(): Boolean {
        var handled = false
        //doAction...
        handled = Random.nextBoolean()
        println("${javaClass.simpleName}处理逻辑... 处理结果:$handled")
        //...
        //如果处理不了,交给下一个处理器
        return handled
    }
}

class HandlerB : HandlerList() {
    override fun handle(): Boolean {
        var handled = false
        //doAction...
        handled = Random.nextBoolean()
        println("${javaClass.simpleName}处理逻辑... 处理结果:$handled")
        //...
        //如果处理不了,交给下一个处理器
        return handled
    }
}


//处理器链
class HandlerChainB {
    private val chainList = mutableListOf<HandlerList>()

    fun addHandle(handler: HandlerList) {
        chainList.add(handler)
    }

    fun handle() {
        for (filter in chainList) {
            if (!filter.handle()) {
                return
            }
        }
    }
}

//调用处:
fun main() {
    val chainB = HandlerChainB()
    chainB.addHandle(HandlerA())
    chainB.addHandle(HandlerB())
    chainB.handle()
}

责任链模式可以将请求和处理分开,请求者无需知道处理流程,只关注处理结果;处理者只关注处理逻辑。两者解耦,提高了系统的灵活性和可扩展性。利用它们来提供框架的扩展点,能够让框架的使用者在不修改框架源码的情况下,基于扩展点定制化框架的功能。

传统的责任链定义是,如果处理器链上的某个处理器能够处理这个请求,那就不会继续往下传递请求。实际上,职责链模式还有一种变体,那就是请求会被所有的处理器都处理一遍,不存在中途终止的情况。比如责任链在网络请求的应用:Okhttp

责任链模式在 Okhttp 中的运用

Okhttp 是移动端网络请求的框架,它内部的网络请求实现就用到了责任链模式。具体实现方式是通过集合存储不同职责的拦截器,保证拦截器执行顺序,并通过递归调用的方式将每个拦截器串联起来,从而支持双向拦截:既能拦截客户端发送的请求,也能拦截服务器返回的响应。

getResponseWithInterceptorChain 是 Okhttp 进行网络请求,获取服务端响应结果的核心方法,会通过几个不同职责的拦截器拿到数据,源码如下:

Response getResponseWithInterceptorChain() throws IOException {
  //装载不同职责的拦截器
  List<Interceptor> interceptors = new ArrayList<>();
  interceptors.addAll(client.interceptors());  //1.这是为客户端预留的拦截器扩展,可以拿到纯净的请求
  interceptors.add(retryAndFollowUpInterceptor); //2.重试和重定向拦截器
  interceptors.add(new BridgeInterceptor(client.cookieJar()));  //3.处理请求和响应的Header,如Content-Length
  interceptors.add(new CacheInterceptor(client.internalCache())); //4.缓存拦截器,如果有缓存则直接返回缓存数据
  interceptors.add(new ConnectInterceptor(client));  //5.构建好TCP链接,确定好编/解码器的拦截器
  if (!forWebSocket) {
    interceptors.addAll(client.networkInterceptors()); //6.也是为客户端预留的拦截器扩展,可以拿到纯净的响应
  }
  interceptors.add(new CallServerInterceptor(forWebSocket)); //7.负责访问服务器并拿到响应结果

  Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
      originalRequest, this, eventListener, client.connectTimeoutMillis(),
      client.readTimeoutMillis(), client.writeTimeoutMillis());

  Response response = chain.proceed(originalRequest);  //8.开始拦截器链式调用
  if (retryAndFollowUpInterceptor.isCanceled()) {
    closeQuietly(response);
    throw new IOException("Canceled");
  }
  return response;
}

拦截器接口定义:

public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    //...
  }
}

具体实现:

public final class RealInterceptorChain implements Interceptor.Chain {
  private final List<Interceptor> interceptors;
  private final int index;

  public RealInterceptorChain(List<Interceptor> interceptors, int index) {
    this.interceptors = interceptors;
    this.index = index;
  }

  @Override public Response proceed(Request request) throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    // 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); //自定义拦截器需要调用chain.proceed继续责任链的调用,通过递归方式穿起来了
    //...
    return response;
  }
}

每个拦截器在内部会封装成 RealInterceptorChain 类型,它内部封装了网络的一些通用逻辑,这个可以忽略,内部还是调用了 intercept 方法传递给下一个拦截器,拦截器中又调用 chain.proceed 继续传递,通过递归的方式将拦截器链串联起来,达到双向拦截的效果,例如下面自定义的拦截器:

public final class CustomInterceptor implements Interceptor {
  @Override public Response intercept(Chain chain) throws IOException {
    //1.对请求进行处理,比如进行gzip压缩
    Response networkResponse = chain.proceed(requestBuilder.build());
	//2.对响应进行处理,比如gzip解压
    return networkResponse;
  }
}

总结

责任链模式是一种非常有用的设计模式,它通过链式结构来组织处理者,实现了请求的灵活处理和系统的可扩展性。

标签:...,拦截器,handle,handled,重修,interceptors,责任,处理器,设计模式
From: https://blog.csdn.net/weixin_39397471/article/details/142568857

相关文章

  • C++—单例设计模式
    单例设计模式C++中的单例设计模式是一种常用的软件设计模式,其核心目的是确保一个类仅有一个实例,并提供一个全局访问点来获取这个实例。以下是对C++单例设计模式的详细解释:一、单例设计模式的定义单例模式(SingletonPattern)是一种创建型设计模式,它确保一个类只有一个实例,......
  • 常用并发设计模式精讲
    1.优雅终止线程的设计模式思考:在一个线程T1中如何优雅的终止线程T2?正确思路:两阶段终止模式1.1两阶段终止(Two-phaseTermination)模式——优雅的终止线程两阶段终止(Two-phaseTermination)模式是一种用于优雅终止线程的设计模式。该模式的基本思想是通过两个阶段来终止......
  • Python设计模式速通
    目录先导对象的事情类的事情方法面对对象程序设计的几个基本要点封装多态继承抽象组合面对对象程序设计的准则开放/封闭原则控制反转原则接口隔离原则单一职责原则替换原则规定三大模式创建型模式结构型模式行为型模式先导我们开始设计模式之前,首先第......
  • 技术成神之路:设计模式(十五)中介者模式
    介绍中介者模式(MediatorPattern)是一种行为型设计模式,用于减少对象之间的复杂通信和依赖。它通过引入一个中介者对象来封装对象之间的交互,从而使得对象之间不直接相互依赖,而是通过中介者进行通信。1.定义中介者模式将对象之间的通信封装到一个中介者对象中,使各对象不再直接引用彼......
  • 设计模式之组合模式
    组合模式组合模式是一种结构型设计模式,用于将对象组织成树形结构以表示部分-整体的层次关系。它使得客户端可以统一地处理单个对象和组合对象。核心概念透明性:组合模式通过使组件的接口包含管理子部件的操作(如添加、删除等),提供了透明的操作方式。这意味着客户端无需关心它正......
  • 设计模式——观察者模式
    设计模式——观察者模式1.天气预报应用案例具体需求:气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方)。需要设计开放型API,便于其他第三方也能接入气象站获取数据。提供温度、气压和湿度的接口测量数据更新时,要能实时的通知......
  • 设计模式_1_单例模式
    单例模式什么是单例设计模式单例模式是一种创建型设计模式,它的核心思想是保证一个类只有一个实例,并提供一个全局访问点来访问这个实例。只有一个实例的意思是,在整个应用程序中,只存在该类的一个实例对象,而不是创建多个相同类型的对象。全局访问点的意思是,为了让其他类能够获......
  • 《程序猿之设计模式实战 · 适配器模式》
    ......
  • 设计模式之中介模式(三分钟学会一个设计模式)
    中介模式(Mediator)又称之为调停模式。mediator[ˈmiːdieɪtə(r)]n.调停者;斡旋者;解决纷争的人(或机构);本意就是解决纠纷的中间人它是面向对象六大原则中最少知道原则的一个典型应用。(关于面向对象六大原则,可看前文:https://www.cnblogs.com/jilodream/p/5353512.html)大概意......
  • 设计模式之适配器模式
    适配器模式适配器模式(AdapterPattern)是一种结构型设计模式,它允许不兼容的接口之间进行交互。在软件工程中,适配器用于解决两个已有接口之间不匹配的问题,使得原本因接口不兼容而不能一起工作的类可以协同工作。基本概念目标接口(Target):客户期望使用的接口,它定义了客户需要的方法......