当前位置: 首页 > news >正文

如何自己实现事件的订阅和发布呢?

1.原理

核心思想是基于发布/订阅模式,用一个共享的数据结构来管理事件和事件监听器。主要功能包括事件订阅、取消订阅、发布事件等功能。

实现思路

  1. 定义事件和监听器接口:首先定义一个 Event 类和一个 EventListener 接口,所有事件和监听器都继承自它们。
  2. 管理订阅关系:使用 Map<Class<? extends Event>, List<EventListener<?>>> 来存储事件类型与监听器的关系。
  3. 发布事件:通过指定事件类型查找所有订阅的监听器,并调用监听器的处理方法。

2.代码工程

Step 1: 定义基础的事件和监听器接口

package com.et;// base event
public abstract class Event {// some basic filed
}
package com.et;// event listen interface
public interface EventListener<T extends Event> {void onEvent(T event);
}

Step 2: 实现 EventBus 类

package com.et;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class EventBus {// store eventprivate final Map<Class<? extends Event>, List<EventListener<? extends Event>>> listeners = new HashMap<>();// Subscribepublic <T extends Event> void register(Class<T> eventType, EventListener<T> listener) {listeners.computeIfAbsent(eventType, k -> new ArrayList<>()).add(listener);}// cancel Subscribepublic <T extends Event> void unregister(Class<T> eventType, EventListener<T> listener) {List<EventListener<? extends Event>> eventListeners = listeners.get(eventType);if (eventListeners != null) {eventListeners.remove(listener);}}// publish@SuppressWarnings("unchecked")public <T extends Event> void post(T event) {List<EventListener<? extends Event>> eventListeners = listeners.get(event.getClass());if (eventListeners != null) {for (EventListener<? extends Event> listener : eventListeners) {((EventListener<T>) listener).onEvent(event); // event forward}}}
}

Step 3: 定义自定义事件和监听器

package com.et;// UserLoginEvent
public class UserLoginEvent extends Event {private final String username;public UserLoginEvent(String username) {this.username = username;}public String getUsername() {return username;}
}

package com.et;public class UserLoginListener implements EventListener<UserLoginEvent> {@Overridepublic void onEvent(UserLoginEvent event) {System.out.println("User logged in: " + event.getUsername());}
}

代码解释

  1. register 方法:将监听器与事件类型绑定。
  2. post 方法:发布事件,找到所有订阅该事件的监听器并通知它们。
  3. unregister 方法:从事件类型的监听器列表中移除指定监听器。

优化建议

  1. 异步处理:可以使用线程池异步发布事件,提高性能。
  2. 过滤器机制:支持对事件的过滤,以便监听器只接收满足条件的事件。
  3. 事件优先级:可以为监听器定义优先级,根据优先级顺序处理。

这种简单的 EventBus 实现适合单进程内的轻量事件传递。如果需要更复杂的功能(如分布式支持、持久化消息),则可以使用成熟的消息代理系统,如 RabbitMQ 或 Kafka。

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • GitHub - Harries/Java-demo(customeMq)

3.测试

package com.et;public class EventBusTest {public static void main(String[] args) {EventBus eventBus = new EventBus();// registerUserLoginListener userLoginListener = new UserLoginListener();eventBus.register(UserLoginEvent.class, userLoginListener);// publishUserLoginEvent loginEvent = new UserLoginEvent("Alice");eventBus.post(loginEvent);// unregistereventBus.unregister(UserLoginEvent.class, userLoginListener);eventBus.post(new UserLoginEvent("Bob")); // don't take effort,because the event is unregister}
}

运行代码,返回结果

User logged in: Alice

http://www.mrgr.cn/news/69614.html

相关文章:

  • Atlassian公司相关信息
  • HarmonyOS SDK下的实践与探索
  • kafka消费数据太慢了,给优化下
  • Conda环境、Ubuntu环境移植
  • kafka 生产经验——数据积压(消费者如何提高吞吐量)
  • 第4章: 图像绘制与文本添加
  • 基于SpringBoot+Vue音乐播放和推荐系统【提供源码+答辩PPT+参考文档+项目部署】
  • PostgreSQL 用户登录失败账号锁定
  • 基于SpringBoot的“生鲜交易系统”的设计与实现(源码+数据库+文档+PPT)
  • numpy np.logical_not函数介绍
  • LLMs在供应链投毒检测中的应用
  • Python中的动态属性管理:使用`__getattr__`和`__setattr__`实现灵活的数据访问
  • 文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于数据-模型混合驱动方法的多类型移动应急资源优化调度策略 》
  • 一文带你看懂Java多线程并发,深度剖析AQS源码
  • 想让水凝胶像智能生物一样行动?光和电怎样赋予其自主 “超能力”?
  • 基于PyQt Python的深度学习图像处理界面开发(一)
  • 【含开题报告+文档+PPT+源码】基于Springboot和vue的电影售票系统
  • 政务培训|LLM大模型在政府/公共卫生系统的应用
  • stm32以太网接口:MII和RMII
  • 前端 性能优化 (图片与样式篇)
  • 【GESP】C++一级真题练习(202312)luogu-B3921,小杨的考试
  • 用 Python 进行建模优化:Pyomo
  • KALI-sqlmap更新
  • 【51单片机】I2C总线详解 + AT24C02
  • 代码随想录刷题记录(二十五)——54. 替换数字
  • RabbitMQ 篇-深入了解延迟消息、MQ 可靠性(生产者可靠性、MQ 可靠性、消费者可靠性)