【问题标题】:Suitable design pattern for event management [closed]适合事件管理的设计模式
【发布时间】:2018-01-31 13:48:42
【问题描述】:

我们有一个模块化架构,其中每个模块都作为事件生成器和事件观察者工作。一个模块可能同时产生多个事件。

我们可以有两种架构来处理事件:

  1. 为不同类型的事件维护一个观察者列表,并一一调用它们的处理程序。

    class Module{
        vector<Module*> event_observer_list[CNT_OF_EVENTS];
        int register(Module* observer, int event_type){
            event_observer_list[event_type].push_back(observer);
        }
        void generate_event(list_of_event_indices){
            for(auto event_index : list_of_event_indices){
                for(auto i : event_observer[event_index])
                    event_observer_list[event_index][i]->handler(some_params);
            }
        }
        int handler(some_params){
            ...
        }
    };
    

    在这种情况下,我们将不得不为多个事件多次调用相同的观察者函数handler()。即使我们写 每个事件都有单独的处理程序,我们可能必须执行一些常见的任务(比如从 每次调用中都有一个同步映射),这使得这种架构变得高效。

  2. 维护一个所有事件通用的观察者列表。我们将一一调用每个模块的处理程序。 如果一个模块不是在寻找某个特定的事件,那么它将跳过处理。

    class Module{
        vector<Module*> event_observer_list;
        int register(Module* observer){
            event_observer_list.push_back(observer);
        }
        void generate_event(list_of_event_types){
            for(i = 0 to event_observer_list.size()){
                event_observer_list[i]->handler(some_params, list_of_event_types);
            }
        }
        int handler(some_params, list_of_event_types){
            ...
        }
    };
    

    这种架构也很高效,因为它让我们调用了一些不必要的处理程序。

请在现有架构中提供任何可能的优化或提供完全不同的设计解决方案。

编辑

epoll(I/O 事件通知工具)API 提供了我正在寻找的类似类型的事件管理工具。它根据注册同时通知多个事件。我试过了,但无法理解他们是如何管理它的。对epoll源代码有很好理解的人可以在这里帮助我。

【问题讨论】:

  • 我看不出两者有什么区别,你只是把调度的职责放到了不同的位置上。除此之外,我想说生成 list of 事件很奇怪恕我直言。
  • @appleapple 我曾经在一个通过 TCP 进行外部通知的系统上工作。为了更有效地传输,我们曾经对事件稍作缓冲,因此发送了一个事件列表。

标签: c++ oop design-patterns event-handling epoll


【解决方案1】:

我认为对此没有什么神奇的解决方案。您想要处理多个事件,并且希望它们由多个观察者处理。

一种可能的优化可能是针对有限数量的事件,您可以将每个不同事件的位标志与每个观察者的位标志相匹配。例如观察者对事件 1,3 和 5(位:0x0015)感兴趣。发送事件 1、2 和 4(位 0x000B),因此调用此观察者的处理程序,因为 0x0015 和 0x000B 不为零(事件 1 很常见)。

两种提议的解决方案的效率差异主要取决于同时发送许多事件的机会。
如果大多数情况下不是这种情况,那么在大多数情况下只调用每个事件感兴趣的观察者会更有效,因为至少并非所有处理程序都必须检查所有事件:每个事件只调用感兴趣的观察者。
当大多数事件可能被发送并且您需要最高效率(这是假设大多数观察者将处理至少一个事件)时,它在负载下的效率可能会稍低。

我更喜欢第一种方法,因为虽然记账有点复杂,但总体而言,您可以期望更有效,尽管在某些情况下方法 2 可能更适合。

【讨论】:

  • 我已经为事件使用了位标志,但为了简单起见,我没有提到它。虽然感谢提及。 +1 建议基于同时发生的事件的机会。我做了一些有问题的编辑,你能帮我吗?
  • 对不起,关于epoll,我可能用select太久了。下次我使用多个连接进行低级通信时,我可能会研究它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-26
  • 2013-01-29
  • 1970-01-01
  • 2020-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多