3

我有一个关于 MVP 设计模式中模型和演示者之间通信的设计问题——或者更准确地说,它从被动视图派生而来。

让我们假设以下简单的 GUI 作为示例:我有一个窗口,其中我的视图是一个列表,并且可以打开一个文件对话框来选择一个文件。一旦我完成了我的选择,文件将被附加到列表中。

我的模型将是我打开的所有文件的集合。

想到一个直接的实现(伪python代码):

解决方案 A

class Model():
     def add(filename):
         # add file
         ...
         # return True if successful
         return True

class Presenter():
    # event from GUI
    def onFileOpen():
        filename = FileSelectorStuff()
        isFileAdded = model.add(filename)
        if isFileAdded:
            view.insertItem(filename)

在这种情况下,我知道文件已添加到模型中,因此我相应地更新了视图。

另一方面,我可以将文件添加到模型中,然后等待模型通知我已更改并且演示者必须更新视图,如下所示:

解决方案 B

class Model():
     def add(filename):
         # add file
         ...
         # alert controller
         modelChanged(Type.FileAdded, filename)

class Presenter():
    # event from GUI
    def onFileOpen():
        filename = FileSelectorStuff()
        model.add(filename)

    # event from model
    def onModelChanged(type, filename):
        if type == Type.FileAdded:
            view.insertItem(filename)
        elif type == Type.FileRemoved:
            ...

现在,在这种情况下,两种实现都可以正常工作。但是让我们假设模型还监视文件,并且需要在其中一个文件被删除时通知演示者。那么无论如何我都需要这种 onModelChanged() 回调机制。

我现在的问题是:我应该混合使用两种更新视图的方式(A 用于同步更新,B 用于异步)还是按照解决方案 B 中的建议将其全部集中在一个地方?

4

1 回答 1

1

这个问题可能早就解决了,但我是从搜索引擎中找到的,所以这是我的答案:

使用 B。忘记混合。

如果要添加 A 位以提高效率,则必须为模型提供两种方法:一种返回布尔值,另一种发出事件。如果同步 Model.add 方法发出事件,则演示者中的事件处理程序将不得不在该方法调用期间忽略它们。凌乱。

然而,我对 Passive View 的理解表明,Presenter 是负责更新模型的人,因此可能有人认为它应该是从模型中删除文件的人,无论如何。这为仅 A 的解决方案铺平了道路。

我的最终答案: 使用 A,或使用 B。不要混用。

于 2011-03-10T06:12:41.833 回答