基于ArkUI Emitter对象实现自定义事件订阅系统 原创
@[toc]
一、引言
在现代计算机编程中,事件驱动编程是一种非常重要的编程范式。它允许程序在特定事件发生时执行相应的操作,从而提高程序的灵活性和可维护性。ArkUI 的 Emitter 对象提供了持续订阅事件、单次订阅事件、取消订阅事件以及触发事件的能力,为我们提供了一个很好的封装参考。
在本文中,我们将探讨如何自己实现一个类似的事件订阅系统。
二、什么是订阅模式
2.1 订阅模式
订阅模式,也称为发布 - 订阅模式(Publish - Subscribe Pattern),是一种消息传递模式,其中发送者(发布者)不会直接将消息发送给特定的接收者(订阅者),而是将消息发布到一个中间的消息代理(通常称为主题或频道),订阅者可以选择订阅他们感兴趣的主题。当有新的消息发布到某个主题时,所有订阅了该主题的订阅者都会收到通知。

2.2 订阅模式的优点
- 松耦合:发布者和订阅者之间不需要直接了解对方的存在,它们只需要通过主题进行通信,从而降低了代码的耦合度。
 - 可扩展性:可以轻松地添加新的发布者和订阅者,而不需要修改现有的代码。
 - 异步通信:发布者和订阅者可以在不同的线程或进程中运行,从而实现异步通信,提高程序的性能。
 
2.3 订阅模式的应用场景
- 消息队列:在分布式系统中,消息队列是一种常见的实现订阅模式的方式,用于实现不同服务之间的异步通信。
 - 事件驱动编程:在图形用户界面(GUI)编程、游戏开发等领域,事件驱动编程是一种常见的编程范式,订阅模式可以用于处理各种事件,如鼠标点击、键盘输入等。
 
三、订阅接口监听器设计
3.1 接口的作用
在设计事件订阅系统时,我们需要定义一个接口来规范订阅者的行为。这个接口通常包含一个方法,用于处理接收到的事件。通过定义接口,我们可以确保所有的订阅者都实现了相同的方法,从而方便发布者调用。
3.2 订阅接口的设计
以下是订阅接口的设计:
# 定义订阅接口
class EventListener:
    def on_event(self, event):
        """
        处理事件的方法
        :param event: 接收到的事件
        """
        raise NotImplementedError("Subclasses should implement this method.")
在这个示例中,定义了一个名为 EventListener 的接口,其中包含一个 on_event 方法。所有实现了这个接口的类都必须实现 on_event 方法,用于处理接收到的事件。
3.3 实现订阅接口
以下是一个实现了 EventListener 接口类:
# 实现订阅接口的类
class MyEventListener(EventListener):
    def on_event(self, event):
        print(f"Received event: {event}")
在这个示例中,定义了一个名为 MyEventListener 的类,它实现了 EventListener 接口的 on_event 方法。当接收到事件时,它会打印出接收到的事件信息。
四、事件类型定义
4.1 事件类型的作用
在事件订阅系统中,不同的事件可能需要不同的处理方式。因此,我们需要定义不同的事件类型,以便订阅者可以根据事件类型来选择是否处理该事件。
4.2 事件类型的设计
以下是一个事件类型定义:
# 定义事件类型
class EventType:
    EVENT_TYPE_1 = "EVENT_TYPE_1"
    EVENT_TYPE_2 = "EVENT_TYPE_2"
在这个示例中,定义了两个事件类型:EVENT_TYPE_1 和 EVENT_TYPE_2。订阅者可以根据这些事件类型来选择是否处理相应的事件。
4.3 事件类的设计
为了方便传递事件信息,我们可以定义一个事件类,包含事件类型和事件数据。以下是一个简单的事件类的设计示例:
# 定义事件类
class Event:
    def __init__(self, event_type, data):
        """
        初始化事件对象
        :param event_type: 事件类型
        :param data: 事件数据
        """
        self.event_type = event_type
        self.data = data
在这个示例中,我们定义了一个名为 Event 的类,它包含两个属性:event_type 和 data,分别表示事件类型和事件数据。
五、自定义Emitter类结构
5.1 Emitter类的功能
自定义的 Emitter 类将实现持续订阅事件、单次订阅事件、取消订阅事件以及触发事件的功能。
5.2 Emitter类的设计
以下是一个自定义 Emitter 类的设计:
class Emitter:
    def __init__(self):
        # 存储持续订阅者的字典,键为事件类型,值为订阅者列表
        self.subscribers = {}
        # 存储单次订阅者的字典,键为事件类型,值为订阅者列表
        self.once_subscribers = {}
    def subscribe(self, event_type, listener):
        """
        持续订阅事件
        :param event_type: 事件类型
        :param listener: 订阅者
        """
        if event_type not in self.subscribers:
            self.subscribers[event_type] = []
        self.subscribers[event_type].append(listener)
    def subscribe_once(self, event_type, listener):
        """
        单次订阅事件
        :param event_type: 事件类型
        :param listener: 订阅者
        """
        if event_type not in self.once_subscribers:
            self.once_subscribers[event_type] = []
        self.once_subscribers[event_type].append(listener)
    def unsubscribe(self, event_type, listener):
        """
        取消订阅事件
        :param event_type: 事件类型
        :param listener: 订阅者
        """
        if event_type in self.subscribers:
            if listener in self.subscribers[event_type]:
                self.subscribers[event_type].remove(listener)
        if event_type in self.once_subscribers:
            if listener in self.once_subscribers[event_type]:
                self.once_subscribers[event_type].remove(listener)
    def emit(self, event):
        """
        触发事件
        :param event: 事件对象
        """
        event_type = event.event_type
        if event_type in self.subscribers:
            for listener in self.subscribers[event_type]:
                listener.on_event(event)
        if event_type in self.once_subscribers:
            for listener in self.once_subscribers[event_type]:
                listener.on_event(event)
            # 清空单次订阅者列表
            self.once_subscribers[event_type] = []
在这个示例中,定义了一个名为 Emitter 的类,它包含以下几个方法:
__init__:初始化Emitter对象,创建两个字典subscribers和once_subscribers,分别用于存储持续订阅者和单次订阅者。subscribe:用于持续订阅事件,将订阅者添加到subscribers字典中。subscribe_once:用于单次订阅事件,将订阅者添加到once_subscribers字典中。unsubscribe:用于取消订阅事件,从subscribers和once_subscribers字典中移除订阅者。emit:用于触发事件,遍历subscribers和once_subscribers字典中相应事件类型的订阅者列表,调用它们的on_event方法处理事件。对于单次订阅者,在处理完事件后,将其从once_subscribers字典中移除。
六、调用示例
6.1 调用代码
# 定义订阅接口
class EventListener:
    def on_event(self, event):
        """
        处理事件的方法
        :param event: 接收到的事件
        """
        raise NotImplementedError("Subclasses should implement this method.")
# 实现订阅接口的类
class MyEventListener(EventListener):
    def on_event(self, event):
        print(f"Received event: {event.event_type}, Data: {event.data}")
# 定义事件类型
class EventType:
    EVENT_TYPE_1 = "EVENT_TYPE_1"
    EVENT_TYPE_2 = "EVENT_TYPE_2"
# 定义事件类
class Event:
    def __init__(self, event_type, data):
        """
        初始化事件对象
        :param event_type: 事件类型
        :param data: 事件数据
        """
        self.event_type = event_type
        self.data = data
# 自定义Emitter类
class Emitter:
    def __init__(self):
        # 存储持续订阅者的字典,键为事件类型,值为订阅者列表
        self.subscribers = {}
        # 存储单次订阅者的字典,键为事件类型,值为订阅者列表
        self.once_subscribers = {}
    def subscribe(self, event_type, listener):
        """
        持续订阅事件
        :param event_type: 事件类型
        :param listener: 订阅者
        """
        if event_type not in self.subscribers:
            self.subscribers[event_type] = []
        self.subscribers[event_type].append(listener)
    def subscribe_once(self, event_type, listener):
        """
        单次订阅事件
        :param event_type: 事件类型
        :param listener: 订阅者
        """
        if event_type not in self.once_subscribers:
            self.once_subscribers[event_type] = []
        self.once_subscribers[event_type].append(listener)
    def unsubscribe(self, event_type, listener):
        """
        取消订阅事件
        :param event_type: 事件类型
        :param listener: 订阅者
        """
        if event_type in self.subscribers:
            if listener in self.subscribers[event_type]:
                self.subscribers[event_type].remove(listener)
        if event_type in self.once_subscribers:
            if listener in self.once_subscribers[event_type]:
                self.once_subscribers[event_type].remove(listener)
    def emit(self, event):
        """
        触发事件
        :param event: 事件对象
        """
        event_type = event.event_type
        if event_type in self.subscribers:
            for listener in self.subscribers[event_type]:
                listener.on_event(event)
        if event_type in self.once_subscribers:
            for listener in self.once_subscribers[event_type]:
                listener.on_event(event)
            # 清空单次订阅者列表
            self.once_subscribers[event_type] = []
# 调用示例
if __name__ == "__main__":
    # 创建Emitter对象
    emitter = Emitter()
    # 创建订阅者对象
    listener1 = MyEventListener()
    listener2 = MyEventListener()
    # 持续订阅事件
    emitter.subscribe(EventType.EVENT_TYPE_1, listener1)
    # 单次订阅事件
    emitter.subscribe_once(EventType.EVENT_TYPE_2, listener2)
    # 触发事件
    event1 = Event(EventType.EVENT_TYPE_1, "Data for event type 1")
    emitter.emit(event1)
    event2 = Event(EventType.EVENT_TYPE_2, "Data for event type 2")
    emitter.emit(event2)
    # 再次触发事件
    event3 = Event(EventType.EVENT_TYPE_2, "Another data for event type 2")
    emitter.emit(event3)
    # 取消订阅事件
    emitter.unsubscribe(EventType.EVENT_TYPE_1, listener1)
    # 再次触发事件
    event4 = Event(EventType.EVENT_TYPE_1, "Data for event type 1 after unsubscribe")
    emitter.emit(event4)
6.2 调用示例解释
- 创建 
Emitter对象:首先创建一个Emitter对象,用于管理事件的订阅和触发。 - 创建订阅者对象:创建两个 
MyEventListener对象listener1和listener2,用于处理事件。 - 持续订阅事件:使用 
subscribe方法让listener1持续订阅EVENT_TYPE_1事件。 - 单次订阅事件:使用 
subscribe_once方法让listener2单次订阅EVENT_TYPE_2事件。 - 触发事件:创建 
Event对象event1和event2,分别表示EVENT_TYPE_1和EVENT_TYPE_2事件,并使用emit方法触发这些事件。 - 再次触发事件:创建 
Event对象event3,再次触发EVENT_TYPE_2事件,由于listener2是单次订阅,所以不会再次处理该事件。 - 取消订阅事件:使用 
unsubscribe方法取消listener1对EVENT_TYPE_1事件的订阅。 - 再次触发事件:创建 
Event对象event4,再次触发EVENT_TYPE_1事件,由于listener1已经取消订阅,所以不会处理该事件。 
七、总结
通过本文的介绍,我们了解了订阅模式的概念、优点和应用场景,并基于 ArkUI 的 Emitter 对象实现了一个自定义的事件订阅系统。设计了订阅接口监听器、定义了事件类型、创建了自定义的 Emitter 类,并提供了完整的调用示例。这个自定义的事件订阅系统可以帮助我们更好地实现事件驱动编程,提高程序的灵活性和可维护性。在实际应用中,可以根据具体需求对这个系统进行扩展和优化,例如添加错误处理、异步处理等功能。





















收藏了🌟🌟