我刚刚参加了一个他们使用GWT和MVP设计的项目。他们使用以下结构:
client.mvp.presenter (contains interfaces)
client.mvp.presenter.impl
client.mvp.view (contains interfaces)
client.mvp.view.impl
在代码中,Presenter知道它的视图,但视图也知道它的演示者,所以我在presenter.impl和view.impl之间的包中找到了循环
再次考虑这个问题,我问自己为什么impl
将自己联系起来而不是仅仅引用接口,从而避免循环。
但我也说“为什么观点应该知道它的主持人?”并且看一些网站谈论MVP,如果视图和主持人应该互相了解,那就不那么清楚了。
什么是最好的?
presenter
并让演示者直接处理用户互动?谢谢!
答案 0 :(得分: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);
}
}
实际上,我通常声明嵌套在视图界面中的演示者界面:
interface FooView extends IsWidget {
interface Presenter {
// ...
}
void setPresenter(Presenter presenter);
// ...
}
class FooPresenter extends AbstractActivity implements FooView.Presenter {
// ...
}
Wrt推测知道impl,最重要的是演示者impl不引用视图impl,因为它会(通常)阻止在没有GWTTestCase
(模拟视图)的情况下进行单元测试。反过来不是问题,但是你真的不需要演示者界面和impl,对吗?
[1]它在技术上可能是视图impl,但它通常是相反的,因此视图可以比演示者更长(演示者通常是轻量级的,与视图相反,由于DOM可能具有不可忽略的创建时间)操作)
答案 1 :(得分:1)
使用MVP,演示者和视图需要知道对应的接口:
请他们使用接口删除循环?
是
要求从视图中删除演示者并让演示者直接处理用户交互?
不,那不是MVP。
什么都不做,通常在MVP中的那些包之间循环
必须保留的循环是实例化循环:您不能将两者作为视图的构造函数参数和视图作为构造函数参数主持人。对于基于构造函数的依赖注入,这变得尤为明显,并且在Java中理论上是不可避免的。但是您可以选择使用setter(至少在一侧),或者使用带有构造函数注入的工厂/ provider。