【Kotlin】一种基于链表结构的事件传播机制设计与实现 - 指南

news/2025/10/11 17:29:16/文章来源:https://www.cnblogs.com/yxysuanfa/p/19135579

事件处理是软件开发中的常见需求,特别是在需要多级处理或事件拦截的场景中。本文将介绍一种基于链表结构的事件传播机制,它采用DSL风格进行链式配置,支持灵活的事件传播路径控制。

设计核心思想

该事件传播机制的核心设计理念是将事件监听器组织成链表结构,每个监听器节点包含事件处理逻辑和指向下一个节点的引用。这种设计使得事件可以沿着预定义的路径顺序传播,为复杂的事件处理流程提供了清晰的解决方案。

关键技术实现

链表节点结构

每个事件监听器节点包含三个关键部分:

  • 事件回调函数:处理具体的事件逻辑
  • 前驱节点指针:指向链表中的上一个节点
  • 后继节点指针:指向链表中的下一个节点
class EventListener<T>() {private var callback: ((T) -> Unit)? = nullprivate var nextListener: EventListener<T>? = nullprivate var parentListener: EventListener<T>? = null}

DSL配置接口

通过DSL(领域特定语言)方式提供流畅的配置接口,使监听器链的构建更加直观:

fun onListener(callback: EventListener<T>.(T) -> Unit): EventListener<T> = lastListener.let { listener ->listener.callback = {callback.invoke(listener, it)}return@let EventListener<T>().apply {parentListener = listenerlistener.nextListener = this@apply}}

这种设计允许开发者以声明式的方式构建事件处理链:

val listener = EventListener<String>().onEvent {println("First: $it")}.onListener {onEvent { println("Second: $it") }}.onListener {onEvent { println("Third: $it") }}

事件传播控制

该机制提供了两种事件触发方式:

  1. 从任意节点开始传播:从当前节点开始,向后继节点依次传播事件
  2. 从根节点完整传播:自动找到链表头部,从头到尾完整执行整个处理链
// 从当前节点开始传播
fun triggerEvent(event: T) {
var current: EventListener<T>? = thiswhile (current != null) {current.callback?.invoke(event)current = current.nextListener}}// 从根节点开始传播fun triggerEventFromRoot(event: T) {rootListener.triggerEvent(event)}

动态链管理

链表结构支持运行时动态调整,每个节点都可以独立地从链中移除:

fun cancel() {
val prev = parentListener
val next = nextListener
prev?.nextListener = next
next?.parentListener = prev
parentListener = null
nextListener = null
callback = null
}

这种设计使得事件处理链可以在运行时根据业务需求动态重组,提高了系统的灵活性。

应用场景分析

该事件传播机制适用于以下场景:

  1. 多层次事件过滤:如GUI事件处理,需要经过多个层次的
  2. 责任链模式实现:每个监听器可以决定是否中断事件传播
  3. 动态功能模块:在运行时根据需要添加或移除处理环节

实现注意事项

在实际使用中需要注意以下几点:

  1. 循环引用风险:节点间相互引用可能导致内存泄漏,需要在适当的时候调用cancel方法清理引用
  2. 异常处理:事件传播过程中某个节点的异常会中断整个传播链
  3. 性能考量:长链表可能影响事件响应性能,需要合理设计链的长度

总结

本文介绍的事件传播机制通过链表结构和DSL配置的结合,提供了一种灵活、可扩展的事件处理方案。其核心价值在于将复杂的事件处理流程转化为清晰的链式结构,同时支持运行时动态调整。这种设计模式在需要精细控制事件传播路径的场景中具有实用价值,为复杂系统的事件处理提供了新的思路。

该机制的实现展示了如何将数据结构理论与实际编程需求相结合,创造出既符合计算机科学原理又满足工程实践需求的解决方案。

完整代码

class EndPropagationChainException : Exception()
class EventListener<T>() {// 事件处理回调函数类型private var callback: ((T) -> Unit)? = null// 链表指针private var nextListener: EventListener<T>? = nullprivate var parentListener: EventListener<T>? = null/*** 设置当前监听器的事件处理回调*/fun onEvent(callback: (T) -> Unit): EventListener<T> {this.callback = callbackreturn this}/*** 设置当前监听器,并添加下一个监听器*/fun onListener(callback: EventListener<T>.(T) -> Unit): EventListener<T> = lastListener.let { listener ->listener.callback = {callback.invoke(listener, it)}return@let EventListener<T>().apply {parentListener = listenerlistener.nextListener = this@apply}}/*** 阻止事件传播*/fun endPropagationChain() {throw EndPropagationChainException()}/*** 获取根节点(链表的起始点)*/private val rootListener: EventListener<T>get() {var root = thiswhile (root.parentListener != null) {root = root.parentListener!!}return root}/*** 获取当前节点的末尾节点*/private val lastListener: EventListener<T>get() {var last = thiswhile (last.nextListener != null) {last = last.nextListener!!}return last}/*** 从当前节点开始向下传播事件*/fun triggerEvent(event: T) {var current: EventListener<T>? = thiswhile (current != null) {try {current.callback?.invoke(event)current = current.nextListener} catch (ignored: EndPropagationChainException) {break}}}/*** 从根节点开始完整传播事件*/fun triggerEventFromRoot(event: T) {rootListener.triggerEvent(event)}/*** 将当前节点从链中移除*/fun cancel() {val prev = parentListenerval next = nextListenerprev?.nextListener = nextnext?.parentListener = prev// 清理当前节点引用parentListener = nullnextListener = nullcallback = null}}fun main() {val listener = EventListener<String>()listener.onListener {println("$this 1接收到事件:$it")}listener.onListener {println("$this 2接收到事件:$it")listener.endPropagationChain()}listener.onListener {println("$this 3接收到事件:$it")}listener.triggerEvent("hello")}

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

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

相关文章

008_函数

1.定义函数 def greet_user(): """显示简单的问候语""" print("Hello!") greet_user() 1.1 向函数传递信息 def greet_user(username): """显示简单的问候语&…

内存分析记录

内存分析记录当碰到 ActivityTaskManager: START u0 {flg=0x10000000 cmp=com.test/com.test.activity.TestActivity} from uid 1000 pid -1 发现pid等于-1,由于是taskview启动,所以需要进一步查找pid信息Line 13009…

详细介绍:构建生产级多模态数据集:视觉与视频模型(参照LLaVA-OneVision-Data和VideoChat2)

详细介绍:构建生产级多模态数据集:视觉与视频模型(参照LLaVA-OneVision-Data和VideoChat2)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !imp…

2025 年图书杀菌机生产厂家最新推荐排行榜:聚焦高效杀菌技术与优质服务,优质企业全面盘点自助图书/臭氧图书/消毒图书/图书杀菌机厂家推荐

随着公共阅读需求的不断增长,图书馆、绘本馆等场所的图书流通频次大幅提升,图书卫生安全问题愈发受到重视。读者在借阅过程中,图书易附着细菌、病毒及灰尘,传统清洁方式难以满足高效杀菌需求,优质图书杀菌机成为必…

公网服务器下的dify安装模型插件的相关问题和操作

公网服务器下的dify安装模型插件的相关问题和操作在前面部署好dify后,我发现安装模型插件出现了一些问题,不知道是有关内存的原因还是什么,在安装模型供应商时非常卡顿。 这是finalshell中的状态,不知道如何解决。…

vscode 生成代码片段

https://snippet-generator.app/

MySQL根据表生成实体类

MySQL根据表生成实体类SELECT CONCAT(/// <summary>\n, ///,column_comment,\n ,/// </summary>, public , ( case LOWER(Data_type) when varchar then string when text then string when tinyint then …

2025票务系统最新推荐榜:高效便捷与用户体验俱佳的优质选择

2025票务系统最新推荐榜:高效便捷与用户体验俱佳的优质选择随着旅游业和娱乐业的快速发展,票务系统的市场需求日益增长。高效的票务系统不仅能够提升用户体验,还能帮助企业提高运营效率。为了帮助筛选票务系统品牌,…

千万公众号运营者必看:8 款编辑器核心能力大 PK

千万公众号运营者必看:8 款编辑器核心能力大 PK一、开篇背景:公众号生态下的创作效率革命 截至2025年,微信公众号数量已突破数千万,编辑器市场规模以年均15%增速扩张至10亿元级别。然而80%的运营者仍受三大痛点困扰…

详细介绍:linux基础服务

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

有度新版本:反向登录、文件路径自定义、有度极速版…管理更自主,切换更顺畅

各位有度用户,大家好! 新版本客户端 (10.0.11) 和服务端 (10.0.0) 已经发布,本次更新带来了反向登录、多语言支持、图片查看器多开等功能,并优化了文件存储与知识库体验,旨在让你在不同场景下的沟通协作更顺畅。一…

C#利用委托实现多个窗体间的传值

原文链接:https://zhuanlan.zhihu.com/p/559679569 要实现这样一个功能:父窗体创建了两个子窗体,子窗体1和子窗体2,1产生的数据要在2中显示出来。 因为这两个子窗体本身之间并没有直接关联,他们都是由父窗体new出…

2025常州微弧氧化批发厂家最新推荐榜:技术领先与优质服务双

2025常州微弧氧化批发厂家最新推荐榜:技术领先与优质服务双随着工业技术的不断进步,微弧氧化技术在金属表面处理领域中扮演着越来越重要的角色。微弧氧化技术通过在金属表面形成一层致密的陶瓷膜,不仅提高了材料的耐…

new操作符的手动实现

function myNew(constructor, ...args) { ​ const obj = Object.create(constructor.prototype);// 创建一个新对象并链接到构造函数的原型​const result = constructor.apply(obj, args);// 将构造函数的 this 指向…

JS使用Regex校验出现卡顿

背景 使用vue3+naive ui 开发网站,在写表单校验规则,其中URL校验项使用了regex,表达式写的有问题,在校验某些URL出现卡顿。最后使用浏览器内置URL类的构建函数来校验,放弃了正则。 REGEX探讨 /^(https?:\/\/)?(…

2025舒适轮胎厂家最新推荐榜:静音耐磨,驾驶体验再升级!

2025舒适轮胎厂家最新推荐榜:静音耐磨,驾驶体验再升级!随着汽车工业的不断发展,消费者对轮胎性能的要求也越来越高。除了基本的安全性和耐用性外,静音和舒适性成为了越来越多车主关注的重点。为了帮助大家更好地筛…

2025 净化铝型材十大品牌之一优选,推荐龙新铝业,最快24小时内发货

“车间急等铝材搭隔断,供应商说要等一周?”“刚发现型材精度不够,半导体车间根本用不了!” 在电子、制药等对洁净环境要求严苛的行业,选对净化铝型材堪比 “定海神针”,而交货慢、品质不稳定更是让无数工程负责人…

2025 权威推荐!净化铝型材品牌 TOP5 排行榜:实力厂家精选,品质之选不容错过

2024年国内工业铝型材产量达1170万吨,同比暴涨23.2%,其中净化专用型材需求增速更是突破19%。但繁荣背后暗藏危机:低价产品用回收铝冒充6063-T5原生铝,铁含量超标导致抗腐性骤降;宣称的"1000小时盐雾测试&quo…

关于HashMap

hashMap的底层数据结构是哈希表,哈希表又由数组加链表构成,在执行put操作时,hashMap会根据key进行哈希函数运算,得到他在数组的位置并插入对应链表,如果哈希值相同并且关键字也相同,那么会直接修改原来的value值…