MVP:演示者模型通信
我有一个关于 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 中的建议将其全部集中在一个位置?
I have a design question about the communication between the model and the presenter in the MVP design pattern -- or more accurately its derived form the passive view.
Let's assume the following simple GUI as an example: I have a window where my view is a list and there is the possibility to open a file dialog to select a file. Once I've finished my selection the file shall be appended to the list.
My model shall be the collection of all files I have opened.
A straight-forward implementation comes to mind (pseudo python code):
Solution 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)
In this case I know that the file was added to the model and thus I update the view accordingly.
On the other hand I could add the file to the model, and then wait for the model to notify me that is has changed and that the presenter has to update the view, like so:
Solution 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:
...
Now, in this case both implementations work just fine. But let's assume that the model also monitors the files and needs to tell the presenter when one of them has been deleted, for example. Then I need this kind of onModelChanged() callback mechanism anyway.
My question now is: Should I mix the two ways for updating the view (A for synchronous updates, and B for async) or rather keep it all central in one place as proposed in solution B?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这个问题可能早已解决,但我从搜索引擎中找到了它,所以这是我的答案:
使用 B。忘记混合。
如果您想添加 A 的位以提高效率,您必须为模型提供两种方法:一种返回布尔值,另一种发出事件。如果同步 Model.add 方法发出事件,则演示器中的事件处理程序将必须在该方法调用期间忽略它们。凌乱的。
但是我对被动视图的理解表明演示者是负责更新模型的人,因此可能会争论说它应该是从模型中删除文件的人。这为唯一的解决方案铺平了道路。
我的最终答案:
使用A,或使用B。不要混合。
This problem is probably long solved, but I hit it from a search engine so here's my answer:
Use B. Forget mixing.
If you want add in bits of A for efficiency you'll have to have two methods for the model: one returning a boolean, the other emitting events. If the synchronous Model.add method emits events, then the event handler in the presenter will have to ignore them during that method call. Messy.
However my understanding of Passive View suggests that the Presenter is the one in charge of updating the Model, so it might be argued that it should be the one to remove files from the Model, anyway. This paves the way for a A only solution.
My Final Answer:
Use A, or use B. Don't mix.