HarmonyOS Next 浅谈 发布-订阅模式

ops/2024/11/25 21:09:41/

HarmonyOS Next 浅谈 发布-订阅模式

前言

其实在目前的鸿蒙应用开发中,或者大前端时代、vue、react、小程序等等框架、语言开发中,普通的使用者越来越少的会碰到必须要掌握设计模式的场景。大白话意思就是一些框架封装太好了,使用者只管在它们的体系下使用就行,哪怕不懂设计模式,也不妨碍我们正常开发业务。但是,如果碰到要封装一些工具、或者游戏开发的时候,那么设计模式的重要性就突显出来了。因为在做封装的时候,如果不使用一些设计模式,那么这些封装的代码基本无法使用。有同感的小伙伴可以踊跃发言。😄

image-20241120214237877

目标

arkts 中,存在 Emitter 对象,它具有持续订阅事件和单次订阅事件、取消订阅事件、触发事件的能力。我们可以将它做为封装的参考,来自己实现一个类似的封装。

Emitter 的使用就是典型的发布-订阅的设计模式。也可以理解为(生产者-消费者设计模式)

  1. 订阅 理解为我们向邮局订阅一些报刊
  2. 发布 理解为报刊发布了,我们自然会受到对应的新报刊
  3. 对于订阅者来说
    1. 我们可以无限时长的订阅报刊(持续订阅)
    2. 我们可以只订阅一次报刊(单次订阅)
    3. 可以取消订阅的报刊
  4. 对于发布者来说
    1. 负责发布即可

接口设计

方法说明
on持续订阅
once单词订阅
off取消订阅
emit发布

具体实现

定义类型

  1. eventType 定义一个事件类型的联合类型,它可以是 normal 或者 once
  2. IEventItem 定义一个事件项的接口,包含事件 ID、类型、回调函数数组以及事件具体类型等属性
// 定义一个事件类型的联合类型,它可以是 "normal" 或者 "once"
type eventType = 'normal' | 'once'// 定义一个事件项的接口,包含事件ID、类型、回调函数数组以及事件具体类型等属性
interface IEventItem {eventId: numbertype: stringcbs: Function[]eventType: eventType
}

定义类的基本结构

  1. MyEmitter 为封装 Emitter 的自定义类的名称
  2. listeners 存储所有事件监听器的私有静态数组,初始为空
  3. _eventId 用于生成唯一事件 ID 的私有静态变量,初始值为 0
  4. **_on ** 私有静态方法,用于添加事件监听器 ,接受事件类型、事件名称和回调函数作为参数
  5. on 静态方法,用于添加普通类型的事件监听器
  6. once 静态方法,用于添加只触发一次的事件监听器
  7. emit 静态方法,用于触发指定类型的事件,会遍历该事件类型对应的所有回调函数并执行它们
  8. off 静态方法,用于移除指定事件 ID 的事件监听器,接受事件 ID 作为必选参数,可选地接受一个回调函数作为参数,如果只传入事件 ID,将移除该 ID 对应的整个事件项;如果同时传入回调函数,将只移除该事件项中对应的回调函数
class MyEmitter {// 存储所有事件监听器的私有静态数组,初始为空private static listeners: IEventItem[] = [];// 用于生成唯一事件ID的私有静态变量,初始值为0private static _eventId: number = 0;// 私有静态属性的getter方法,每次调用返回递增后的_eventId值// 用于获取下一个可用的事件IDprivate static get eventId() {}// 私有静态方法,用于添加事件监听器// 接受事件类型、事件名称和回调函数作为参数private static _on(eventType: eventType, type: string, cb: Function) {}// 静态方法,用于添加普通类型的事件监听器// 接受事件名称和回调函数作为参数// 内部调用私有静态方法 _on 并传入 "normal" 事件类型static on(type: string, cb: Function) {}// 静态方法,用于添加只触发一次的事件监听器// 接受事件名称和回调函数作为参数// 内部调用私有静态方法 _on 并传入 "once" 事件类型static once(type: string, cb: Function) {}// 静态方法,用于触发指定类型的事件// 接受事件名称作为必选参数,可选地接受一个数据参数// 会遍历该事件类型对应的所有回调函数并执行它们static emit<T = undefined>(type: string, data?: T) {}// 静态方法,用于移除指定事件ID的事件监听器// 接受事件ID作为必选参数,可选地接受一个回调函数作为参数// 如果只传入事件ID,将移除该ID对应的整个事件项;如果同时传入回调函数,将只移除该事件项中对应的回调函数static off(eventId: number, cb?: Function) {}

调用示例

@Entry
@Component
struct Index {tid: number = -1build() {Column({ space: 10 }) {Button("1 注册常规事件").onClick(() => {this.tid = MyEmitter.on("login", (res: object) => {console.log(JSON.stringify(res))})})Button("1 取消常规事件").onClick(() => {MyEmitter.off(this.tid)})Button("1 触发常规事件").onClick(() => {MyEmitter.emit("login", 100)})Button("2 注册一次性事件").onClick(() => {this.tid = MyEmitter.once("login2", (res: object) => {console.log(JSON.stringify(res))})})Button("2 取消一次性事件").onClick(() => {MyEmitter.off(this.tid)})Button("2 触发一次性事件").onClick(() => {MyEmitter.emit("login2", 100)})Button("3 注册具名事件").onClick(() => {this.tid = MyEmitter.on("login1", this.fn1)})Button("3 取消具名事件").onClick(() => {MyEmitter.off(this.tid, this.fn1)})Button("3 触发具名事件").onClick(() => {MyEmitter.emit("login1", 300)})}.height('100%').width('100%')}fn1(n: number) {console.log("具名事件", n)}
}

效果图

image-20241120220915524

总结

发布 - 订阅模式是一种非常有用的软件设计模式,它可以实现系统的解耦、可扩展性和灵活性。在实际应用中,需要根据具体的需求和场

景选择合适的实现方式

作者

作者:万少

链接:https://www.nutpi.net/

來源:坚果派 著作权归作者所有。

商业转载请联系作者获得授权,非商业转载请注明出处。


http://www.ppmy.cn/ops/136667.html

相关文章

河道水位流量一体化自动监测系统:航运安全的护航使者

在广袤的水域世界中&#xff0c;航运安全始终是至关重要的课题。而河道水位流量一体化自动监测系统的出现&#xff0c;如同一位强大的护航使者&#xff0c;为航运事业的稳定发展提供了坚实的保障。 水位传感器&#xff1a;负责实时监测河道的水位变化。这些传感器通常采用先进的…

基于Java Springboot汽车4s店管理系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

国土变更调查拓扑错误自动化修复工具的研究

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、拓扑错误的形成原因 1.边界不一致 2.不规则图形 3.尖锐角 4.局部狭长 5.细小碎面 6.更新层相互重叠 二、修复成果展示 1.边界不一致 2.不规则图形 3.尖锐角 4.局部狭…

IEC61850读服务器目录命令——GetServerDirectory介绍

IEC61850标准中的GetServerDirectory命令是变电站自动化系统中非常重要的一个功能&#xff0c;它主要用于读取服务器的目录信息&#xff0c;特别是服务器的逻辑设备节点&#xff08;LDevice&#xff09;信息。以下是对GetServerDirectory命令的详细介绍。 目录 一、命令功能 …

Linux 进程概念与进程状态

目录 1. 冯诺依曼体系结构2. 操作系统&#xff08;Operator System&#xff09;2.1 概念2.2 设计OS的目的2.3 系统调用和库函数概念 3. 进程概念3.1 描述进程 - PCB3.2 task_struct3.3 查看进程3.4 通过系统调用获取进程标识符PID&#xff0c; PPID3.5 通过系统调用创建fork 4.…

数据结构-图的遍历

一.深度优先搜素 遍历&#xff1a;把图中的每一个顶点访问一遍 把自己所能看见灯任意点亮然后依次进行点亮操作,当自己所能看见的灯全都被点亮&#xff0c;也不能直接从节点退出&#xff0c;而是回退然后继续进行上述操作 当所有的灯都被点亮了,一定要原路返回直到返回到出口…

C++之旅-set和map掌握篇

目录 前言 1.set的使用 1.1set类的介绍 1.2 set的构造和迭代器 1.3 set的增删查 1.4 代码练习 1.4.1 set的构造&#xff0c;插入与删除 1.4.2 set 的find的使用样例&#xff0c;与erase结合 1.4.3 set获取区间值函数的应用 1.5 multiset和set的差异 1.6 set强化练习&…

什么是反向 DNS 查找以及它的作用是什么?

反向DNS查询&#xff08;rDNS&#xff09;是一种技术&#xff0c;用于确定与某个IP地址对应的域名。当我们对一个IP地址进行反向DNS查询时&#xff0c;实际上是向域名系统&#xff08;DNS&#xff09;的特殊部分请求信息&#xff0c;这部分被称为PTR记录。PTR记录会返回与这个I…