2012-11-14 92 views
4

我想开发一个基于处理某些事件并生成数据的系统。每个事件将包含(可能)几个不同的字段,每个侦听器将处理一些或他们。我心目中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中不是这种情况,因为我们只是生成另一组侦听器并将它们注册到事件生成类。

你们对这些有什么看法?他们是有道理的,还是你会建议完全不同的?

回答

3

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

如果性能是最关心的问题,那么使用大型开关/大小块切换整数事件id的集中控制器可能会最快。 ...并且随着时间的推移最不灵活/可维护。您可能想要查看Guava project's EventBus。它使用注释来注册事件监听器,并为这种类型的事件广播/订阅提供了一个非常干净的api。事件订阅者根据他们在方法签名中声明的事件类型进行通知。这是非常光滑的,并节省了大量的样板。我不知道它会如何扩展到数千种事件类型,但与一些类似的图书馆不同,事件总线不是全球性的。您可以创建不同的事件总线实例来分离事件处理,只要这样做有意义。

0

这听起来像你是在一个相当大的和(可能)复杂的开始。在使用你提到的两种更重要的启发式方法之前,我可能会仔细研究一下基于事件的编程。这个想法与使用监听器非常相似,只是异步实现,所以事件监听器可以是他们自己的小线程,只有当他们被要求采取行动时才会起作用。

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

在我看来,主要好处是责任在被照顾之前委派给(子)听众。在一个真正可以帮助程序员的大环境中,它可以防止性能瓶颈。我相信这也被称为reactor pattern

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