如何在MVP中创建视图? Presenter是否始终创建它们(除了子视图的视图外)?或者它是一个单独的第三方组件或应用程序或创建它们的东西?
我们还要补充一点,我可能会在Dojo Toolkit / ExtJS(即JavaScript)上执行此操作。
所以,我有这些代码行:
var v = new MyApp.view.User();
var p = new MyApp.presenter.User();
两条线应该在哪里准确?演示者是否实例化视图,反之亦然?什么实例化第一个实例?
答案 0 :(得分:45)
这取决于......
MVP的主要目标是将复杂的决策逻辑与UI代码分开,使其变得更容易理解和维护。通常另一个目标是使演示者的决策逻辑可测试。
Fowler在2004年描述了MVP模式,他retired it in 2006将模式分为Supervising Conroller(SC)和Passive View(PV)。在SC中,View与模型绑定,但在PV中不绑定;在PV中,View只能由Presenter直接更改。
在SC和PV中,演示者必须更新视图和对用户对视图所做的更改做出反应,例如输入文本或按下按钮。当您在Presenter上使用View调用方法时,会出现您描述的问题,因为View需要对Presenter的引用,反之亦然。如果您这样做,您只需决定谁将其全部启动。选项包括:
所有选项都可以让您达到关注点分离和决策逻辑可测性提高的“MVP目标”。我不认为这些方法中的任何一种在理论上是正确的或错误的 - 您只需选择最适合您使用的技术的方法。在整个应用程序中,最好保持一致的选择。
答案 1 :(得分:6)
以下是您的选择:
var cvp = new ContactViewPresenter(new ContactView());
ContactViewPresenter
构造函数集this.view = viewParam
,并设置this.view.presenter = this
。
它将代码保留在Presenter中,它可以在必要时交换视图,并且可以通过模拟视图进行测试。
var cv = new ContactView(new ContactViewPresenter());
ContactView
构造函数集this.presenter = cvpParam
和this.presenter.view = this
。
View中的一些逻辑,但不是很多。如有必要,可以换出演示者。
ContactView cv = new ContactView();
ContactViewPresenter cvp = new ContactViewPresenter();
cv.presenter = cvp;
cvp.view = cv;
cv.init();
cvp.init();
这是更多的代码。
ContactViewPresenter cvp = new ContactViewPresenter();
构造函数创建集this.view = new ContactView()
和this.view.presenter = this
。
ContactView cv = new ContactView();
构造函数集this.presenter = new ContactViewPresenter()
和this.presenter.view = this
最后两个看起来有点太耦合了。
一个很好的是代码保留在Presenter中,似乎可以更容易地进行测试。
两个很好,因为你不必过多关心演示者,并且可以更多地担心你的观点。
答案 2 :(得分:2)
我不认为Presenter应该实例化视图,这应该由MVP三元组之外的实体(不是面向数据的意义上,我指的是一般实体)来完成。例如,控制反转(IoC)框架(如果您还没有听说过IoC,请检查Martin Fowler's article),或者某些负责用户配置的应用程序模块。
答案 3 :(得分:0)
如果您使用的是WebForms,则WebForm OnLoad或Init应该是您创建Presenter的位置 - 然后将其传递给WebForm实现的View的接口引用。
所以,像这样:
Presenter _presenter;
OnLoad(object sender, EventArgs e)
{
_presenter = new Presenter(this);
_presenter.Initialise();
}
因此定义了Presenter构造函数:
public class Presenter
{
public Presenter(IView viewReference)
{
_viewReference = viewReference;
}
}
答案 4 :(得分:0)
我的术语可能略有错误,但我认为您需要确定交互的组成根;什么是开始互动的东西?
在我给出的Webforms示例中,Webform是由Http管道创建的,OnInit或OnLoad事件是管道中的第一个点(取决于您需要的上下文),您可以“挂钩”到该进程。因此,您可以创建一个Presenter,并将其作为View Interface的具体Web实例提供给它。
我不知道你正在讨论的Javascript框架,但我认为有一个初始化/调用步骤 - 在ASP.NET MVC中,当涉及ActionInvoker时,它是控制台应用程序中的Main。