写点什么

HarmonyOS Next 浅谈 发布 - 订阅模式

作者:万少
  • 2024-12-15
    江苏
  • 本文字数:2411 字

    阅读完需:约 8 分钟

HarmonyOS Next 浅谈 发布-订阅模式

HarmonyOS Next 浅谈 发布-订阅模式

前言

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


目标

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


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


  1. 订阅 理解为我们向邮局订阅一些报刊

  2. 发布 理解为报刊发布了,我们自然会受到对应的新报刊

  3. 对于订阅者来说

  4. 我们可以无限时长的订阅报刊(持续订阅)

  5. 我们可以只订阅一次报刊(单次订阅)

  6. 可以取消订阅的报刊

  7. 对于发布者来说

  8. 负责发布即可

接口设计

具体实现

定义类型

  1. eventType 定义一个事件类型的联合类型,它可以是 normal 或者 once

  2. IEventItem 定义一个事件项的接口,包含事件 ID、类型、回调函数数组以及事件具体类型等属性


// 定义一个事件类型的联合类型,它可以是 "normal" 或者 "once"type eventType = "normal" | "once";
// 定义一个事件项的接口,包含事件ID、类型、回调函数数组以及事件具体类型等属性interface IEventItem { eventId: number; type: string; cbs: 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的私有静态变量,初始值为0  private static _eventId: number = 0;
// 私有静态属性的getter方法,每次调用返回递增后的_eventId值 // 用于获取下一个可用的事件ID private 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@Componentstruct Index {  tid: number = -1
build() { 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) }}
复制代码

效果图

总结

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


景选择合适的实现方式


发布于: 刚刚阅读数: 4
用户头像

万少

关注

还未添加个人签名 2021-12-02 加入

还未添加个人简介

评论

发布
暂无评论
HarmonyOS Next 浅谈 发布-订阅模式_鸿蒙_万少_InfoQ写作社区