我正在使用一个基于Eclipse RCP的框架,该框架具有效率低下的事件模型。具体来说,控件发出的事件通常是“级联”的。例如,一个控件将发出一个COLOR_CHANGED事件,使父组合将事件传播给同级控件,而同级控件又决定发出自己的COLOR_CHANGED事件(以响应原始事件),从而导致各种连锁反应。我已经描述了该应用程序引发了100,000多个事件,以呈现一个简单的表单。坦白说,我不明白它是如何不会溢出堆栈的。

因此,我正在寻找一种防止或减少这种级联行为的技术或设计模式。我有一些想法,但这不是一个新问题。对于面向事件的设计,已经存在一种“最佳实践”。

我的想法:

  • 事件的运行就像堆栈跟踪一样,因此新事件被链接到其原因。这使侦听器可以忽略源自自己的事件。但是,这使我的事件模型变得非常复杂(包装标准SWT事件将很繁琐)。更不用说有一些实际的用例,您可能实际上需要这种行为。
  • 中央“事件泵”用于引发事件。如果事件在最近n毫秒内具有与先前引发的事件相同的源和有效负载,则将其丢弃。希望这会产生掺杂效果,并防止事件级联。显然,我无法控制如何引发SWT / RCP事件,但是这些不是我的主要关注点。
  • 应该输入事件。这似乎是倒退,但我认为更细粒度的事件将有助于提高性能。例如,ValidationFailedEvent而不是每个人都处理的通用Event(然后必须询问其状态以确定事件类型)。

  • 感谢您抽出宝贵的时间来阅读我的问题。欢迎所有建议/建议。

    编辑:感谢pablosaraiva,我阅读了有关Chain-of-responsibility的信息,现在有了以下想法:
  • 事件公开isHandled属性,如果将其设置为true,则将阻止事件传播。当了解事件的范围时,此方法应该起作用,但如果单个控件无法“处理”事件,则无济于事。
  • 最佳答案

    这些年来,我一直在尝试许多不同的方法。解决此问题的基本方法是让模型仅在实际更改时才发出事件。对于模型中的每个类,这会使模型稍微复杂一些,但这是我设法使这种范例起作用的唯一方法。

    例如

    public void setColor(Color c)
    {
       setBackground(c);
       notify(new ColorChangedEvent(this, c));
    }
    

    会成为
    public void setColour(Color c)
    {
        if (!getBackground().equals(c))
        {
           setBackground(c);
           notify(new ColorChangedEvent(this, c));
        }
    }
    

    Java中的标准Observable类通过'setChanged()'方法支持此功能。

    实现此功能的一种更简单的方法(但恕我直言,效果不佳)是使“通知”关闭监听,直到完成通知为止。也就是说,通知看起来像
    private iAmNotifying;
    public void notify(Event e)
    {
        if (!iAmNotifying)
        {
            iAmNotifying = true;
            doTheActualNotification(e);
            iAmNotifying = false;
        }
    }
    

    但这在粒度方面有一些明显的缺点,第一种方法取得了更好的成功。

    07-28 02:34
    查看更多