栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

设计模式之责任链模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

设计模式之责任链模式

文章目录
  • 责任链模式
    • 定义
    • 实现
      • 简单实现
        • UML类图
        • 代码实现
      • 筛选请求实现
        • UML类图
        • 代码实现
      • OkHttp责任链的模仿实现
        • UML类图
        • 代码实现
    • 拓展
    • 总结
    • 参考文献

责任链模式

定义

责任链模式是行为型设计模式之一

行为型模式关注的是对象之间的通信,也就是描述多个类或者对象之间,通过协作共同完成一个任务。主要涉及的是 对象 和 算法之间职责的分配。

行为型模式 可以分为两类:

  • 类行为模式: 通过继承机制来在类间分派行为。 主要是通过多态来分配父类和子类的职责
  • 对象行为模式: 通过组合或聚合,在对象间分派行为。通过对象关联等方式来分配类的职责。

由于组合方式比继承耦合性低,所以对象行为模式要比类行为模式具有更大的灵活性。所以大部分的行为型设计模式 都是 对象行为模式。

责任链模式则是对象行为模式的一种。

链即链条,链必然会存在节点。类比狗狗的链子,其中的圆环可以拆卸和添加,因此链式结构具有很好的灵活性。而在责任链模式中,每个节点就是一个对象,每个对象拥有不同的处理逻辑,发起请求后,链头先获取请求,再往后遍历,类似链表的遍历,前面的节点有权利选择是否处理,拦截还是继续往下传递。

每个设计模式都有其优缺点,责任链模式的优缺点如下:

优点:
避免了请求的发送者和接收者之间的耦合关系,且不同的请求处理者之间也进行了职责隔离。

缺点:
节点太多可能导致遍历性能下降,如果是递归则更要慎重。

实现

带着上述的优点和缺点,进入实现环节。

简单实现

节点之间采用链表的形式存储,每个节点都对处理进行相应。

实现一个对String进行加工的功能.

UML类图

节点的共同父类为Handler,子类继承并实现父类的抽象方法handle()

代码实现

Handler

abstract class Handler(protected val nextHandler: Handler?) {
    abstract fun handle(request: String): String
}

Handler1

class Handler1(handler: Handler?) : Handler(handler) {
    override fun handle(request: String): String {
        //Handler1自己的处理
        val newRequest = "$request -> Handler1处理请求"
        return nextHandler?.handle(newRequest) ?: newRequest
    }
}

Handler2

class Handler2(handler: Handler?) : Handler(handler) {
    override fun handle(request: String): String {
        //Handler2自己的处理
        val newRequest = "$request -> Handler2处理请求"
        return nextHandler?.handle(newRequest) ?: newRequest
    }
}

Main

fun main() {
    val handler1 = Handler1(Handler2(null))
    println(handler1.handle("request"))

}

最终结果为:

request -> Handler1处理请求 -> Handler2处理请求

上述实现是责任链模式最简单的实现,体现出不同的处理者之间的职责隔离,自己处理自己的逻辑,假设说有一个需求,此需求需要先做A操作,再做B操作才能实现,那么就可以使用上述中责任链模式实现,创建两个处理者,分步处理。

筛选请求实现

上述的实现中,所有的请求每个节点都需要必须经过,在现实情况中,请求可能需要分类,某些请求可能不需要经过某些处理者,下面实现一个筛选请求的需求。

根据请求码,选择相应处理器进行处理。

UML类图

创建Request类,内部包含处理的数据,声明getRequestCode()方法,返回请求码,Handler获取Request的相应码与自己进行对比判断是否需要处理。

代码实现

Handler

abstract class Handler(protected var nextHandler: Handler?) {

    fun handleRequest(request: Request) {
        //若请求码相等则自己处理,否则向下传递
        if (getCode() == request.getRequestCode()) {
            handle(request)
        } else {
            nextHandler?.handleRequest(request) ?: println("没有处理者处理此请求")
        }
    }

    //获取Handler的请求码
    protected abstract fun getCode(): Int

    //具体的处理逻辑
    protected abstract fun handle(request: Request)

}

MyHandler1

class MyHandler1(nextHandler: Handler?) : Handler(nextHandler) {

    override fun getCode() = 100

    override fun handle(request: Request) {
        println("${request.getContent()} MyHandler1处理")
    }
}

MyHandler2

class MyHandler2(nextHandler: Handler?) : Handler(nextHandler) {

    override fun getCode() = 200

    override fun handle(request: Request) {
        println("${request.getContent()} MyHandler2处理")
    }

}

MyHandler3

class MyHandler3(nextHandler: Handler?) : Handler(nextHandler) {

    override fun getCode() = 300

    override fun handle(request: Request) {
        println("${request.getContent()} MyHandler3处理")
    }
    
}

Request

 class Request(private val obj: Any, private val code: Int) {

    fun getContent() = obj

     fun getRequestCode() = code
}

Main

fun main() {
    val request1 = Request("first request", 100)
    val request2 = Request("second request", 200)
    val request3 = Request("third request", 300)
    val request4 = Request("fourth request", 400)
    //创建责任链 MyHandler1 -> MyHandler2 -> MyHandler3
    val handler = MyHandler1(MyHandler2(MyHandler3(null)))
    
    handler.handleRequest(request1)
    handler.handleRequest(request2)
    handler.handleRequest(request3)
    handler.handleRequest(request4)
}

打印结果如下:

first request MyHandler1处理
second request MyHandler2处理
third request MyHandler3处理
没有处理者处理此请求

request4没有处理者处理因此打印没有处理者处理此请求

上述实现是最简单的筛选,直到找到完全相等的Code才会被处理,假设需求改变,责任链上只要Handler code比Request code高或者相等则必须执行该怎么修改呢?

只需修改Handler类中的handleRequest()方法

修改如下:

Handler#handleRequest

fun handleRequest(request: Request) {
    //若请求码大于等于则命中
    if (getCode() >= request.getRequestCode()) {
        handle(request) 
    }
    //无论命中if都往下传递请求
    nextHandler?.handleRequest(request) ?: println("后续没有处理者相应了")
}
OkHttp责任链的模仿实现

回想网络请求的过程,客户端发送Request,服务端收到请求后返回Response,客户端再处理此Response,整个过程时一条链的过程,因此使用责任链可以实现。

回想OkHttp的使用:

fun get() {
    //创建OkHttpClient
    val okHttpClient = OkHttpClient()
    val url = "https://www.baidu.com"
    val request = Request.Builder()
        .url(url)
        .build()
    val call = okHttpClient.newCall(request)
    call.enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            Log.d("get", "onFailure")
        }
        override fun onResponse(call: Call, response: Response) {
            val responseBody = response.body;
            if (responseBody != null)  {
                Log.d("get", responseBody.string())
            }
        }

    })
}

只需要简单的构建一个Request,再调用Call的执行方法即可获取到Response,那HTTP的请求重定向,请求头的封装,底层和Socket的交互是谁做的呢,就是OkHttp中的拦截器。

OkHttp认为从Request到Response需要经历很多步骤,每个步骤都是不同且独立的,因此可以使用责任链模式实现,在OkHttp的责任链上有处理重定向的节点,有处理封装请求头的节点,有负责和底层Socket交互的节点。

下面简单实现OkHttp的责任链模式

UML类图

声明链条类,不再使用链表,降低了拦截器之间的耦合,客户端只关注于链条返回的结果,不再关注于具体的处理者,隔离了用户和真正的处理者,在请求发起后从第一个拦截器开始逐步向下执行,最终由最后一个拦截器发出请求,由于是最后一个拦截器发出的请求,因此最后一个拦截器也将最先获取响应,然后将Response逐步返回。

代码实现

Interceptor

public interface Interceptor {
    String intercept(Chain chain);
}

RetryAndFollowUpInterceptor

public class RetryAndFollowUpInterceptor implements Interceptor {
    @Override
    public String intercept(Chain chain) {
        //可以在执行下一个拦截器之前,做自己的事情
        System.out.println("开始执行重试重定向拦截器");
        // 执行下一个拦截器
        String result = chain.processd(chain.request + "==>经过重试重定向拦截器");
        //获得结果后,加一些自己的东西
        System.out.println("结束执行重试重定向拦截器");
        return result + "==>经过重试重定向拦截器";
    }
}

BridgeInterceptor

public class BridgeInterceptor implements Interceptor {
    @Override
    public String intercept(Chain chain) {
        System.out.println("开始执行桥接拦截器");
        String result = chain.processd(chain.request + "==>经过桥接拦截器");
        System.out.println("结束执行桥接拦截器");
        return result + "==>经过桥接拦截器";
    }
}

CacheInterceptor

public class CacheInterceptor implements Interceptor {

    @Override
    public String intercept(Chain chain) {
        System.out.println("开始执行缓存拦截器");
        String result = chain.processd(chain.request + "==>经过缓存拦截器");
        System.out.println("结束执行缓存拦截器");
        return result + "==>经过缓存拦截器";
    }
}

ConnectInterceptor

public class ConnectInterceptor implements Interceptor {

    @Override
    public String intercept(Chain chain) {
        System.out.println("开始执行连接拦截器");
        String result = chain.processd(chain.request + "==>经过连接拦截器");
        System.out.println("结束执行连接拦截器");
        return result +"==>经过连接拦截器";
    }
}

CallServerInterceptor

public class CallServerInterceptor implements Interceptor {

    @Override
    public String intercept(Chain chain) {
        System.out.println("开始执行请求服务器拦截器");
        System.out.println("===发起请求===");
        System.out.println("结束执行请求服务器拦截器");
        return chain.request + "==>经过请求服务器拦截器nHttp响应==>经过请求服务器拦截器";
    }
}

Chain

public class Chain {
    private List interceptors;
    private int index;
    public String request;

    public Chain(List interceptors, int index, String request) {
        this.interceptors = interceptors;
        this.index = index;
        this.request = request;
    }

    public Chain(List interceptors, int index) {
        this.interceptors = interceptors;
        this.index = index;
    }

    public String processd(String request) {
        if (index >= interceptors.size()) {
            throw new AssertionError();
        }
        Chain chain = new Chain(interceptors, index + 1, request);
        Interceptor interceptor = interceptors.get(index);
        return interceptor.intercept(chain);
    }
}

Main

public class Main {

    public static void main(String[] args) {
        List interceptors = new ArrayList<>();
        interceptors.add(new RetryAndFollowUpInterceptor());
        interceptors.add(new BridgeInterceptor());
        interceptors.add(new CacheInterceptor());
        interceptors.add(new ConnectInterceptor());
        interceptors.add(new CallServerInterceptor());
        //链条对象
        Chain chain = new Chain(interceptors, 0);
        System.out.println(chain.processd("Http请求"));

    }
}

打印结果如下:

开始执行重试重定向拦截器
开始执行桥接拦截器
开始执行缓存拦截器
开始执行连接拦截器
开始执行请求服务器拦截器
=发起请求=
结束执行请求服务器拦截器
结束执行连接拦截器
结束执行缓存拦截器
结束执行桥接拦截器
结束执行重试重定向拦截器
Http请求==>经过重试重定向拦截器==>经过桥接拦截器==>经过缓存拦截器==>经过连接拦截器==>经过请求服务器拦截器
Http响应==>经过请求服务器拦截器==>经过连接拦截器==>经过缓存拦截器==>经过桥接拦截器==>经过重试重定向拦截器

拓展

在Android事件分发中也使用了责任链模式,View树等价于责任链,从顶点开始找到可以响应事件的子View,具体的事件分发请看读者的另一篇文章Android事件分发机制详解

总结

责任链模式非常灵活,可用的地方很多。

既可以多个对象处理同一请求,也可以一个对象只处理一个请求,主要优点则是避免了请求的发送者和接收者之间的耦合关系,且不同的请求处理者之间也进行了职责隔离。

参考文献

何红辉和关爱民老师的《Android 源码设计模式解析与实战》

✨ 原 创 不 易 , 还 希 望 各 位 大 佬 支 持 一 下 textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下

 点 赞 , 你 的 认 可 是 我 创 作 的 动 力 ! textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!

⭐️ 收 藏 , 你 的 青 睐 是 我 努 力 的 方 向 ! textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!

✏️ 评 论 , 你 的 意 见 是 我 进 步 的 财 富 ! textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/943286.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号