1

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

我将此命名为“委托事件”,因为我认为事件发起控件的中介必须将事件委托给选定控件(或其模型)的中介 - 但问题是,“如何?”

背景

MGM 模式有点像MVP Passive View,除了每个控件都有一个单独的“中介”(而不是每个表单一个演示者)。控件的事件全部由其中介处理,中介调用其特定模型的方法作为响应。中介者是模型的观察者,当模型改变时更新它的控制。它特别适用于您的控件没有数据绑定并且您不想对它们进行子类化的 RAD 环境。与被动视图不同,它还有一个优点是连接事件的样板代码很少。这里有两个更详细的描述:

问题示例

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

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

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

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

但是菜单项的中介者是如何找到选中控件的中介者的呢?

在 MGM 中,中介对象应该是自包含的,所以不知道其他中介对象。不允许控件了解有关模型的任何信息(以保持关注点的清晰分离)。控件唯一了解其中介者的是事件处理程序。

黑客解决方法

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

但这似乎严重依赖于语言特性(TMethod),并且还创建了中介类之间的依赖关系。

也许我完全走错了路……</p>

(PS 可以比我有更多代表的人创建一个“model-gui-mediator”标签吗?谢谢。)

4

1 回答 1

2

以防万一将来有人看到这个问题,我找到了“官方”答案。

在 MGM(和被动视图)中,模型应该包含所有必要的状态信息。所以在这种情况下,应用程序模型将跟踪哪个是焦点控件。

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

(这实际上不是我采用的解决方案。状态信息已经包含在 GUI 中,我不想在模型中复制它 - 将相同的信息保存在多个位置并且具有高度引入不一致的不良可能性。这可能是 MGM 和被动视图等模式的弱点之一。无论如何,我采用了我在问题中描述的“hacky”解决方法。)


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

例如,如果一个控件能够保存其内容,则在模型中定义一个 OnSave 事件并让中介者连接一个调用控件中保存功能的处理程序。然后模型的 Save 方法只调用事件,控件负责实现,而模型不必知道任何有关它的信息。

于 2013-08-23T07:29:05.663 回答