Kotlin~责任链模式

news2024/11/19 11:19:49

概念

允许多个对象按顺序处理请求或任务。

角色介绍

  • Handler: 处理器接口,提供设置后继者(可选)
  • ConcreteHandler:具体处理器,处理请求

UML

责任链

代码实现

atm

比如ATM机吐钱就可以使用责任链实现。

class PartialFunction<in P1, out R>(
    private val definetAt: (P1) -> Boolean,
    private val f: (P1) -> R
) : (P1) -> R {
    override fun invoke(p1: P1): R {
        if (definetAt(p1)) {
            return f(p1)
        } else {
            throw IllegalAccessException()
        }
    }

    fun isDefinedAt(p1: P1) = definetAt(p1)
}

/**
 * orElse 方法种可以传入另一个 PartialFunction 类对象 that,它也就是责任链模式中的后继者
 * infix 关键字让 orElse 成为一个中缀函数,从而让责任链调用的语法变得更加直观
 */
infix fun <P1, R> PartialFunction<P1, R>.orElse(that: PartialFunction<P1, R>): PartialFunction<P1, R> {
    return PartialFunction({
        this.isDefinedAt(it) || that.isDefinedAt(it)
    }) {
        when {
            this.isDefinedAt(it) -> this(it)
            else -> that(it)
        }
    }
}

什么是偏函数?

在Scala中偏函数使用PartialFuncation构建只处理输入参数的部分分支的函数,也就是带判断条件的函数。在python中作用就是把一个函数的某些参数给固定住(也就是设置成默认值),返回一个新的函数。这样调用的时候就会比较简单。

data class Current(var cash: Int, val message: MutableList<String>)

val RMB_5 = run {
    val definetAt: (Current) -> Boolean = { it.cash >= 5 }
    val handler: (Current) -> Unit = {
        println("处理5元")
        val num = it.cash / 5
        it.cash = it.cash % 5
        it.message.add("5元 * $num")
    }
    PartialFunction(definetAt, handler)
}
val RMB_10 = run {
    val definetAt: (Current) -> Boolean = { it.cash >= 10 }
    val handler: (Current) -> Unit = {
        println("处理10元")
        val num = it.cash / 10
        it.cash = it.cash % 10
        it.message.add("10元 * $num")
    }
    PartialFunction(definetAt, handler)
}
val RMB_20 = run {
    val definetAt: (Current) -> Boolean = { it.cash >= 20 }
    val handler: (Current) -> Unit = {
        println("处理20元")
        val num = it.cash / 20
        it.cash = it.cash % 20
        it.message.add("20元 * $num")
    }
    PartialFunction(definetAt, handler)
}
val RMB_50 = run {
    val definetAt: (Current) -> Boolean = { it.cash >= 50 }
    val handler: (Current) -> Unit = {
        println("处理50元")
        val num = it.cash / 50
        it.cash = it.cash % 50
        it.message.add("50元 * $num")
    }
    PartialFunction(definetAt, handler)
}
val RMB_100 = run {
    val definetAt: (Current) -> Boolean = { it.cash >= 100 }
    val handler: (Current) -> Unit = {
        println("处理100元")
        val num = it.cash / 100
        it.cash = it.cash % 100
        it.message.add("100元 * $num")
    }
    PartialFunction(definetAt, handler)
}

fun ATMMachine(atmChain: PartialFunction<Current, Unit>, cash: Current): Int {
    atmChain(cash)
    return if (cash.cash < 5) {
        if (cash.cash > 0) {
            cash.message.add("1元 * ${cash.cash}")
        }
        0
    } else {
        ATMMachine(atmChain, cash)
    }
}

fun main(args: Array<String>) {
    val atmChain = RMB_100 orElse RMB_50 orElse RMB_20 orElse RMB_10 orElse RMB_5
    val user = Current(1084, ArrayList<String>())
    ATMMachine(atmChain, user)
    for (s in user.message) {
        println(s)
    }
}

优缺点

优点

  • 分离发送着和接收者
  • 链中的灵活性
  • 易于扩展和维护

缺点

  • 无法保证处理请求
  • 性能开销较大
  • 调试复杂度高

应用场景

有多个对象可以处理请求,动态添加、删除修改请求处理器。

  • 中间件
  • GUI时间处理器
  • 异常处理
  • 工作流

总结

责任链平时在业务开发中使用较少,像OkHttp网络请求框架就使用了责任链模式。它里面定义了主要以下几个拦截器:

  • RetryAndFollowUpInterceptor : 负责失败重试和重定向

  • BridgeIntezceptor : 负责处理http 通用请求头和返回头,Cookie

  • CacheInterceptor : 负责处理缓存

  • ConnectInterceptor : 开启和服务器的连接

  • networkInterceptors : 用户定义的网络拦截器,权限更高,更接近底层,一般不需要关注

  • CallServerInterceptor : 实现网络请求

具体可以参考OKHTTP源码解析

  • OKHttp源码解析(二)-责任链_okhttp责任链_夏屿_的博客
  • Okhttp之责任链

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/726560.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【环境配置】Conda ERROR:Failed building wheel for lap

问题 note: This error originates from a subprocess, and is likely not a problem with pip.ERROR: Failed building wheel for lapRunning setup.py clean for lap Failed to build lap ERROR: Could not build wheels for lap, which is required to install pyproject.to…

JDK8安装

在官网进行下载Java Downloads | Oracle 点击进行安装即可。 之后是配置环境变量 点击我的电脑 – 属性 – 高级系统设置 – 环境变量 添加JAVA_8_HOME环境变量&#xff0c;指向jdk的安装目录。 之后编辑path环境变量&#xff0c;增加%JAVA_8_HOME%\bin win R 输入javac 测…

在线支付安全-业务安全测试实操(35)

目前网络在线消费和支付,已遍布人们生活的衣食住行等冬个方面,比如网上商城在线购物、水电燃气在线缴费、手机话费在线充值等。由于在线消费和支付过程中涉及真金白银,一旦存在漏洞,将会带来重大的经济损失。 某快餐连锁店官网订单金额篡改 篡改订单金额的流程如图 所示 步…

Spark(14):SparkSQL之概述

目录 0. 相关文章链接 1. SparkSQL是什么 2. Hive and SparkSQL 3. SparkSQL 特点 3.1. 易整合 3.2. 统一的数据访问 3.3. 兼容Hive 3.4. 标准数据连接 4. DataFrame 是什么 5. DataSet 是什么 6. SparkSQL的运行环境 0. 相关文章链接 Spark文章汇总 1. SparkSQL是…

java pdf加水印

本文将Base64编码形式的pdf文件加水印&#xff0c;并输出完成后的pdf的Base64编码&#xff0c;也可以根据情况自行改动&#xff0c;输出其他形式的内容。 首先引入两个包 <!-- PDF文件依赖包 --><dependency><groupId>com.itextpdf</groupId><arti…

计算机体系结构基础知识介绍之缓存性能的十大进阶优化之编译器优化和硬件预取(六)

优化七&#xff1a;编译器优化&#xff0c;降低miss率 处理器和主内存之间不断扩大的性能差距促使编译器编写者仔细检查内存层次结构&#xff0c;看看编译时优化是否可以提高性能。再次&#xff0c;研究分为指令缺失的改进和数据缺失的改进。接下来介绍的优化可以在许多现代编…

步入JAVA——环境搭建与项目通览

前言 在这篇文章中&#xff0c;荔枝会介绍如何配置Java后端开发环境并借助一个Java web项目简单介绍一下Java的后端开发逻辑。与python的后端开发逻辑是类似的&#xff0c;Java的后端开发其实也是通过一个个类来实现的。对于像荔枝这种小白白来说&#xff0c;入门的第一个练手J…

java项目之高校四六级报名管理系统(ssm+jsp+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的高校四六级报名管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风歌…

mysql执行顺序以及为什么别名不能用在 where 后

1、mysql执行顺序 如下&#xff1a; 1. from 阶段 2. where 阶段 3. group by 阶段 4. having 阶段 5. select 阶段 6. order by 阶段 7. limit 阶段 2、为什么别名不能用在 where 后

微信小程序反编译之后运行报错“_typeof3 is not a function”

微信小程序解包之后&#xff0c;在微信开发者工具当中点开调试器&#xff0c;选择Console选项卡&#xff0c;发现左侧的预览界面是空白的&#xff0c;虽然真机调试可以有显示&#xff0c;但是真机预览也是跟左边的界面一样都是空白。之后发现Console里面显示 解决方法&#x…

7.5~7.6学习成果总结

关于封装&#xff0c;满足几个原则&#xff0c;一般的成员变量用privat修饰&#xff0c;仅暴露少量方法获取&#xff0c;如果是内部的操作方法也用private&#xff0c;除非是希望被全局使用&#xff0c;的才考虑用public&#xff0c;如果是进希望被子类用的话可以考虑用protect…

ICG NH2,1686147-55-6,吲哚菁绿氨基,安全性更好,并具有更好的光稳定性

ICG NH2&#xff0c;ICG-Amine&#xff0c;吲哚菁绿氨基|&#xff08;文章编辑来源于&#xff1a;西安凯新生物科技有限公司小编WMJ&#xff09;产品结构式&#xff1a; 对于ICG NH2&#xff08;1686147-55-6&#xff09;我们需要知道这些&#xff1a; CAS号为1686147-55-6&am…

专项练习21

目录 一、选择题 1、下列逻辑表达式的结果为false的是&#xff08;&#xff09; 2、请问以下JS代码输出的结果是什么&#xff1f; 3、以下哪些对象是Javascript内置的可迭代对象&#xff1f; 二、编程题 1、找到数组参数中的最大值并返回。注意&#xff1a;数组中只包含数字 …

16 直线识别拟合角平分线(matlab程序)

1.简述 直线检测是数字图像处理的重要内容,在道路识别,建筑物识别,医学图像分析等领域都有十分重要的应用。通过对已经获得的图像进行边缘检测,然后用Hough变换对边缘检测进行直线检测。该方法简单,受直线中的间隙和噪声影响较小。在Matlab环境下对该方法进行了仿真实验,并对图…

【LLM】Windows本地CPU部署民间版中文羊驼模型(Chinese-LLaMA-Alpaca)踩坑记录

目录 前言 准备工作 Git Python3.9 Cmake 下载模型 合并模型 部署模型 前言 想必有小伙伴也想跟我一样体验下部署大语言模型, 但碍于经济实力, 不过民间上出现了大量的量化模型, 我们平民也能体验体验啦~, 该模型可以在笔记本电脑上部署, 确保你电脑至少有16G运行…

1.4 计算机网络性能

1.4 计算机网络性能 速率带宽延迟/时延(delay或latency)四种分组延迟排队延迟 时延带宽积分组丢失&#xff08;丢包&#xff09;吞吐量/率&#xff08;Throughput&#xff09; 速率 速率即数据率(data rate)或称数据传输速率或比特率(bit rate) 单位时间&#xff08;秒&#x…

为什么我心中TOP1的编程语言是Java?我为什么选择Java?

文章目录 前言优点跨平台性面向对象编程&#xff08;OOP&#xff09;强大的类库和工具支持广泛的应用领域 缺点速度相对较慢内存消耗较大较高的学习曲线 Java 学习路线总结前置知识Web前端基础 后端基础1. Java基础2. 数据库技术3. Web开发技术4. 框架技术5. 服务器部署 其他技…

KKT条件

有两种情况&#xff1a; 原问题是非凸函数原问题是凸函数 &#xff08;1&#xff09;非凸函数 KKT是强对偶的必要条件&#xff0c;而不是充分条件&#xff0c;即KKT不能推出强对偶。 &#xff08;2&#xff09;凸函数 KKT与强对偶互为充要条件。 下面给出具体的KKT条件&a…

数据结构--二叉树的先中后序遍历

数据结构–二叉树的先中后序遍历 二叉树的遍历 层次遍历 层次遍历:基于树的层次特性确定的次序规则 二叉树的递归特性: ①要么是个空二叉树 ②要么就是由“根节点左子树右子树”组成的二叉树 先 \color{red}先 先序遍历&#xff1a; 根 \color{red}根 根左右&#xff08; N \…

springboot 集成log4j日志,需要自定义json格式内容输出方便ES采集

背景 公司需要将服务迁移到K8S环境上&#xff0c;由于目前服务输出的格式不符合ES进行采集的日志格式&#xff0c;所有需要将日志输出的格式进行调整为JSON格式&#xff0c;方便ES采集 遇到的坑 之前是直接配置的输出格式的message为"message": %msg"&#x…