在Model-GUI-Mediator Pattern中委派事件(可能还有MVP?)

时间:2013-08-16 14:42:50

标签: design-patterns mvp mediator

当一个事件触发应该作用于聚焦控件(而不是触发事件的控件)时,如何在Model-GUI-Mediator(MGM)模式中处理?我怀疑如果您有多个模型,这个问题也适用于密切相关的MVP pattern

我将这个'委托事件'命名为因为我认为事件发起控件的调解员必须将事件委托给所选控件(或其模型)的调解器 - 但问题是,'如何?'< / p>

背景

MGM模式有点像MVP Passive View,除了您为每个控件(而不是每个表单一个演示者)都有一个单独的“中介”。控件的事件都由其中介处理,并且中介调用其特定模型的方法作为响应。介体是模型的observer,并在模型更改时更新其控制。它特别适用于RAD环境,在该环境中,您的控件没有数据绑定,并且您不希望将它们子类化。与Passive View不同,它还具有连接事件的样板代码非常少的优点。以下是两个更详细的描述:

问题示例

  1. 表单包含许多控件,这些控件提供许多模型对象的视图。一次只能选择其中一个视图。 (如果你想要一些具体的东西,想象一下多文档编辑器。)

  2. 用户从菜单调用命令。这将调用特定菜单项的mediator对象中的Execute方法。 (菜单项是一个控件,因此它有一个相应的中介。)

  3. 该命令应该对当前选定的控件执行操作。

  4. 因此菜单项的介体需要找到属于所选控件的介体并在那里委托操作,或者需要找到与所选控件的介体关联的模型并直接调用它。

  5. 但是菜单项的介体如何找到所选控件的介体?

    在MGM中,中介对象应该是自包含的,因此不了解其他中介对象。不允许控件了解模型的任何信息(以保持明确的关注点分离)。控件知道他们的调解员的唯一事情是事件处理程序。

    Hacky解决方法

    到目前为止,我提出的最好的方法是检查所选控件中的事件字段,该字段将是指向该控件的介体的对象方法指针。在Delphi中,我可以将它转换为TMethod,从而为控件的中介提取对象指针。然后我可以将它转换为调解器的类型并调用所需的方法。

    但这似乎很大程度上依赖于语言功能(TMethod),并且还会在介体类之间创建依赖关系。

    也许我完全走错了轨道......

    (P.S。可能会有比我更多代表的人请创建一个“模型gui-mediator”标签?谢谢。)

1 个答案:

答案 0 :(得分:2)

如果将来有人看到这个问题,我找到了“官方”答案。

在MGM(和Passive View)中,模型应包含所有必要的状态信息。因此,在这种情况下,应用程序模型将跟踪哪个是集中控制。

在多文档编辑器的示例中,您将拥有一个处理各种菜单命令的应用程序模型,并跟踪当前具有焦点的编辑器。然后将工作委托给与焦点编辑器对应的编辑器模型很容易。

(这实际上不是我采用的解决方案。状态信息已经包含在GUI中,我不想在模型中复制它 - 在多个地方保持相同的信息总是显得笨拙引入不一致性的可能性很大。这可能是MGM和被动视图等模式的一个弱点。无论如何,我采用了我在问题中描述的'hacky'解决方法。)


就像脚注一样,处理这种情况的另一种方法 - 控件处理许多功能并声明您不想在模型中复制但模型需要访问的状态 - 是定义事件在它需要访问所述功能/状态时可以调用的模型中。使用事件可以将调解员依赖性保留在模型之外,这是MGM的基本要求和存在理由。

例如,如果控件具有保存其内容的能力,请在模型中定义OnSave事件,并让介体挂钩调用控件中的save功能的处理程序。然后模型的Save方法只调用事件,控件负责实现,而模型不需要知道任何事情。