2

我刚刚参加了一个他们使用 GWT 和 MVP 设计的项目。他们使用以下结构:

client.mvp.presenter (contains interfaces)
client.mvp.presenter.impl
client.mvp.view (contains interfaces)
client.mvp.view.impl

在代码中,Presenter 知道它的视图,但视图也知道它的 Presenter,所以我在 Presenter.impl 和 view.impl 之间的包中找到了循环

再想一想,我问自己为什么要impl链接自己而不是只引用接口,从而避免循环。

但我也认为“为什么视图应该知道它的演示者?” 并且查看一些谈论 MVP 的网站,如果视图和演示者应该相互了解,则不清楚。

什么是最好的?

  • 要求他们使用接口去除循环?
  • 要求presenter从视图中删除并让演示者直接处理用户交互?
  • 什么都不做,MVP 中的这些包之间通常有循环

谢谢 !

4

2 回答 2

3

实际上,虽然演示者 impl [1] 现在需要视图(界面),但演示者界面通常不需要。

典型的模式是:

interface FooPresenter {
   // methods called by the view (generally in response to user interaction)
   void doSomething(String foo);
}

interface FooView {
   /** Tells the view which presenter instance to call back. */
   void setPresenter(FooPresenter presenter);

   // methods called by the presenter to control the view
   void showSomething(String foo);
}

class FooPresenterImpl implements FooPresenter {
    private final FooView view;

    FooPresenterImpl(FooView view, /* other dependencies here */) {
       this.view = view;
    }

    // could also be the start() method of com.google.gwt.activity.shared.Activity
    public void init() {
       view.setPresenter(this);
    }

    // optional; could be called from onStop() and onCancel() if using Activity
    public void dispose() {
       view.setPresenter(null);
    }
}

实际上,我通常将 Presenter 接口声明为嵌套在视图接口中:

interface FooView extends IsWidget {

    interface Presenter {
       // ...
    }

    void setPresenter(Presenter presenter);

    // ...
}

class FooPresenter extends AbstractActivity implements FooView.Presenter {
   // ...
}

Wrt impls 知道 impls,最重要的是演示者 impl 不引用视图 impl,因为它(通常)会阻止在没有GWTTestCase(模拟视图)的情况下对其进行单元测试。反过来问题不大,但是您并不真的需要演示者界面与 impl,对吗?

[1] 从技术上讲,它可能是视图 impl,但通常是相反的,因此视图可以比演示者更长寿(演示者通常是轻量级的,与视图相反,由于 DOM 操作,视图可能具有不可忽略的创建时间)

于 2012-10-03T10:39:28.243 回答
1

使用 MVP,presenter 和 view 需要知道对应的接口

  • 演示者通常需要更新视图
  • 当事件(例如ValueChangeEvents)发生时,视图调用presenter 方法。

要求他们使用接口去除循环?

是的。

要求从视图中删除演示者并让演示者直接处理用户交互?

不,那不会是MVP。

什么都不做,MVP 中的这些包之间通常有循环

必须保留的循环是实例化循环:您不能同时将演示者作为视图的构造函数参数,并将视图作为演示者的构造函数参数。这在基于构造函数的依赖注入中变得尤为明显,并且在 Java 中理论上是不可避免的。但是您可以选择使用 setter(至少在一侧),或者使用带有构造函数注入的工厂/提供程序。

于 2012-10-03T10:18:45.033 回答