调解员模式(也可能是MVP?)
当一个事件触发,应该对焦点控件(而不是触发该事件的控件)进行操作时,如何在Model-GUI-Mediator(MGM)模式中处理这个事件? 我怀疑这个问题也适用于密切相关的MVP模式,如果你有多个模型。
我称之为“授权事件”,因为我认为事件源控制的中介必须将事件委托给所选控件(或其模型)的中介 - 但问题是,'如何?'
背景
MGM模式有点像MVP被动视图,除了每个控件有一个单独的“中介”(而不是每个表单的一个演示者)。 控件的事件全部由其中介处理,中介调用其特定模型的方法作为响应。 介体是模型的观察者,并在模型更改时更新其控件。 它特别适用于您的控件没有数据绑定并且不想子类化的RAD环境。 与被动视图不同,它的优点是只有很少的样板代码来连接事件。 这里有两个更详细的描述:
问题示例
表单包含许多控件,这些控件提供了许多模型对象的视图。 一次只能选择其中一个视图。 (如果你想要一些具体的东西,可以想象一个多文档编辑器。)
用户从菜单调用命令。 这将调用特定菜单项的中介对象中的Execute方法。 (菜单项是一个控件,因此它有一个相应的中介。)
该命令应该对当前选定的控件执行一个操作。
因此,菜单项的介体需要找到属于所选控件的介体,并在那里委托该操作,或者需要找到与所选控件的介体相关联的模型并直接调用该模型。
但是,菜单项的介体如何找到所选控件的介体?
在MGM中,中介对象应该是独立的,所以不知道其他中介对象。 不允许控件知道任何有关模型的内容(保持明确的关注点分离)。 控件只知道其中介是事件处理程序。
哈克解决方法
到目前为止我所得到的最好的结果是检查选定控件中的事件字段,它将成为该控件中介的对象方法指针。 在Delphi中,我可以将它转换为TMethod并因此提取控件中介的对象指针。 然后,我可以将其转换为中介的类型并调用所需的方法。
但是这似乎严重依赖于语言特性(TMethod),并且还会在中介类之间创建依赖关系。
也许我完全在错误的轨道上......
(PS可以请比我更多的人请创建一个“model-gui-mediator”标签吗?谢谢。)
以防万一以后有人看到这个问题,我找到了'官方'的答案。
在MGM(和被动视图)中,模型应该包含所有必要的状态信息。 因此,在这种情况下,应用程序模型会跟踪哪个是重点控制。
在多文档编辑器的例子中,您将有一个应用程序模型来处理各种菜单命令,并跟踪哪个编辑器当前有焦点。 将工作委托给与重点编辑器对应的编辑器模型很容易。
(这实际上并不是我采用的解决方案,状态信息已经包含在GUI中,我不想在模型中复制它 - 它总是将笨拙的信息保存在多个地方,并且具有高度的这可能是MGM和Passive View等模式的一个弱点,无论如何,我采用了我在问题中描述的'hacky'解决方法。)
就像脚注一样,处理这种情况的另一种方式是控制处理大量功能并声明不希望在模型中复制但模型需要访问该功能的方法是在模型中定义事件它可以在需要访问所述功能/状态时调用。 使用事件可以保持模型中的中介依赖,这是MGM的基本要求和存在理由。
例如,如果控件能够保存其内容,请在模型中定义一个OnSave事件,并让中介钩住一个调用控件中保存功能的处理程序。 模型的Save方法然后调用事件,并且控件负责实现,而模型不需要知道任何事情。
链接地址: http://www.djcxy.com/p/35363.html