Java事件处理设计



我正在尝试开发一个基于处理某些事件和生成数据的系统。每个事件将包含(可能)几个不同的字段,每个侦听器将处理其中一些字段。有以下两种方法

  1. 在事件生成类中,我将注册多个事件侦听器,每个侦听器侦听事件的特定字段的一个特定值,例如:

    public class MicroListener implements Listener {
    public void processEvent(Event e){
    if(e.getName().equals(registeredName)) { ... }
    }
    

这很诱人,因为处理是在对象本身内完成的,并且没有对事件进行集中处理,而是允许每个对象处理信息。缺点,可能是致命的,是每一个事件(几十万)都必须向所有听众广播,而只有一小部分人会真正用它做一些事情。从长远来看,它可能会产生巨大的表演冲击。。。

  1. 一个集中式侦听器,它将侦听并对所有事件采取行动,并将处理委托给相应的事件处理器,例如:

    public class CentralListener implements Listener {
    Map<String, Processor> processorsByName;
    public void processEvent(Event e){
    processorsByName.get(e.getName()).process(e);
    }
    }
    

这会更快,但它需要单独的映射或事件任何其他部分的处理器集合,例如检查事件ID等的处理器。方法1中的情况并非如此。因为我们只需生成另一组监听器,并将它们注册到事件生成类中。

你们觉得这些怎么样?它们有道理吗?还是你宁愿为完全不同的事情提供建议?

这是一个常见的设计决策,我不认为有一个通用的答案对所有(甚至大多数)情况都是正确的。我可以列出两种方法中的各种权衡,但它们可能是显而易见的。在考虑可能的性能影响之前,我更喜欢最适合概念模型的设计(并且不会创建一堆无关的类)。

如果性能是最重要的问题,那么使用大型交换机/机箱块切换整数事件ID的集中式控制器可能是最快的。。。并且随着时间的推移也是最不灵活/可维护的。

您可能需要查看Guava项目的EventBus。它使用注释来注册事件侦听器,并为这种类型的事件广播/订阅提供了一个非常干净的api。根据事件订阅者在其方法签名中声明的事件类型来通知事件订阅者。它相当光滑,节省了很多样板。我不知道它能扩展到数千种事件类型,但与一些类似的库不同,事件总线不是全局的。当有意义时,您可以创建不同的事件总线实例来分离事件处理

听起来你正处于一个相当大且(可能)复杂的事物的开端。在使用您提到的两种更具启发性的方法之前,我可能会仔细研究一下基于事件的编程。这个想法与使用侦听器非常相似,只是异步实现,因此事件侦听器可以是自己的小线程,只在被要求执行时才执行。

我不知道它在这里是否适用,但让我们假设您有不同的事件类型,需要传播到不同的侦听器。与其将观察者存储在一个巨大的堆中,为什么不为观察者可以注册的每个事件类型创建一个侦听器呢?如果您有一些生成事件的核心组件,它们可以在侦听器上发送,然后再次将它们发送给观察者。

在我看来,主要的好处是在得到照顾之前,将责任委托给(次级)听众。在一个可以真正帮助程序员的大型环境中,它可以防止性能瓶颈。我相信这也被称为反应堆模式。

如果你正在寻找灵感,试着看看akka框架。它是为高效的分布式事件编程而设计的。

最新更新