MVP:Presenter与Model的通信
我有一个关于MVP设计模式中模型和展示者之间沟通的设计问题,或者更准确地说,是它的派生形式——被动视图。
假设我们有一个简单的图形界面作为例子:我有一个窗口,里面有一个列表,并且可以打开一个文件对话框来选择文件。一旦我完成选择,这个文件就应该被添加到列表中。
我的模型就是我打开的所有文件的集合。
我想到了一种简单的实现方式(伪代码):
方案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所建议的那样,把所有内容集中在一个地方?
1 个回答
1
这个问题可能早就解决了,但我在搜索引擎上看到,所以我来分享一下我的看法:
用B。别混合使用。
如果你想为了效率而加入一些A的部分,你就得为模型准备两个方法:一个返回布尔值(也就是真或假),另一个用来发出事件。如果同步的Model.add方法发出事件,那么在这个方法调用期间,展示者中的事件处理程序就得忽略这些事件。这会让事情变得很麻烦。
不过,根据我对被动视图的理解,展示者应该负责更新模型,所以可以说它应该负责从模型中移除文件。这样就为只用A的解决方案铺平了道路。
我的最终建议: 用A,或者用B。别混合使用。