事件引起连锁反应

时间:2011-08-19 02:40:53

标签: java events swt

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

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

我的想法:

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

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

编辑:感谢pablosaraiva,我读到了Chain-of-responsibility,现在有了以下想法:

  • 事件公开isHandled属性,如果设置为true,将阻止事件传播。这应该在事件的范围被理解时起作用,但如果事件不能由单个控件“处理”则无效。

1 个答案:

答案 0 :(得分:1)

多年来,我一直在玩这种方法。您可以采取的基本措施是让模型仅在实际发生变化时才发出事件。这使得模型中的每个类的模型稍微复杂一些,但这是我设法使这个范例有效的唯一方法。

例如

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()'方法支持它。

实现这一点的一种稍微简单的方法(但恕我直言并不是那么好)是让'notify'关闭监听,直到它完成通知。也就是说,通知看起来像

private iAmNotifying;
public void notify(Event e) 
{ 
    if (!iAmNotifying)
    {
        iAmNotifying = true;
        doTheActualNotification(e);
        iAmNotifying = false;
    }
}

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