Skip to main content
 首页 » 编程设计

python之MVP:Presenter-Model 通信

2025年05月04日9mq0036

我有一个关于 MVP 设计模式中模型和演示者之间的通信的设计问题——或者更准确地说,它源自被动 View 。

让我们以下面的简单 GUI 为例:我有一个窗口,其中我的 View 是一个列表,并且可以打开一个文件对话框来选择一个文件。完成选择后,文件将附加到列表中。

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

想到一个直接的实现(伪 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) 

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

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

方案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()回调机制。

我现在的问题是:我应该混合使用两种更新 View 的方法(A 用于同步更新,B 用于异步),还是如解决方案 B 中所建议的那样将所有内容集中在一个地方?

请您参考如下方法:

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

使用 B。忘记混合。

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

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

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