5

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

  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中不是这种情况。因为我们将简单地生成另一组侦听器并注册他们与事件生成类。

你们怎么看这些?它们有意义吗,还是您宁愿建议完全不同的东西?

4

2 回答 2

4

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

如果性能是最受关注的问题,那么在整数事件 id 上使用大型 switch/case 块切换的集中式控制器可能是最快的。...随着时间的推移,也是最不灵活/可维护的。

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

于 2012-11-14T22:21:29.053 回答
0

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

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

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

如果您正在寻找灵感,请尝试查看akka 框架。它专为高效的分布式事件编程而设计。

于 2012-11-14T22:40:45.077 回答