在 MVP 中如何创建视图?演示者是否总是创建它们(除了在子视图的情况下查看)?或者它是一个单独的第三方组件或应用程序或创建它们的东西?
我们还要补充一点,我可能会在 Dojo Toolkit/ExtJS(即 JavaScript)上执行此操作。
所以,我有这些代码行:
var v = new MyApp.view.User();
var p = new MyApp.presenter.User();
两条线到底应该去哪里?演示者是否实例化视图,反之亦然?什么实例化了第一个实例?
在 MVP 中如何创建视图?演示者是否总是创建它们(除了在子视图的情况下查看)?或者它是一个单独的第三方组件或应用程序或创建它们的东西?
我们还要补充一点,我可能会在 Dojo Toolkit/ExtJS(即 JavaScript)上执行此操作。
所以,我有这些代码行:
var v = new MyApp.view.User();
var p = new MyApp.presenter.User();
两条线到底应该去哪里?演示者是否实例化视图,反之亦然?什么实例化了第一个实例?
这取决于 ...
MVP 的主要目标是将复杂的决策逻辑从 UI 代码中分离出来,以便更容易理解和维护。通常另一个目标是使演示者中的决策逻辑可测试。
MVP 模式由 Fowler 在 2004 年描述,他在 2006 年将其拆分为监督控制器(SC) 和被动视图(PV)。在 SC 中,View 与 Model 绑定,但在 PV 中没有;在 PV 中,View 仅由 Presenter 直接更改。
在 SC 和 PV 中,Presenter 必须更新 View并对用户对 View 所做的更改做出反应,例如输入文本或按下按钮。当您让 View 调用 Presenter 上的方法时,就会出现您描述的问题,因为 View 需要对 Presenter 的引用,反之亦然。如果您这样做,您只需决定由谁来启动它。选项是:
所有选项都允许您达到关注点分离和决策逻辑可测试性增加的“MVP 目标”。我认为这些方法中的任何一种在理论上都没有对错——您只需选择最适合您使用的技术的方法即可。最好在整个应用程序中保持一致。
这些是您的选择:
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 中,并且似乎允许更轻松的测试。
二是很好,因为您不必过多关心演示者,并且可以更多地担心您的视图。
我不认为 Presenter 应该实例化视图,这应该由 MVP 三元组之外的实体(不是面向数据的意义上,我的意思是一般实体)来完成。例如,一个控制反转 (IoC) 框架(如果您还没有听说过 IoC,请查看Martin Fowler 的文章),或者一些负责用户配置的应用程序模块。
我的术语可能略有错误,但我认为您需要确定互动的构成根源;开始互动的东西是什么?
在我给出的 Webforms 示例中,Webform 由 Http 管道创建,OnInit 或 OnLoad 事件是管道中的第一个点(取决于您需要的上下文),您可以“挂钩”到流程中。因此,您创建了一个 Presenter 并将您的 Webform 的具体实例作为视图接口提供给它。
我不知道您正在讨论的 Javascript 框架,但我认为有一个初始化/调用步骤 - 在 ASP.NET MVC 中,这是涉及 ActionInvoker 的时候,它是控制台应用程序中的 Main。
如果您使用的是 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;
}
}