我刚刚参与了一个使用 GWT 和 MVP 设计的项目。它们使用以下结构:
client.mvp.presenter (contains interfaces)
client.mvp.presenter.impl
client.mvp.view (contains interfaces)
client.mvp.view.impl
在代码中,Presenter知道它的view,但view也知道它的presenter,所以我在package中发现了presenter.impl和view.impl之间的循环
再次思考这个问题,我问自己为什么 impl
链接自身而不是仅引用接口(interface),从而避免循环。
但我也想“为什么 View 应该知道它的呈现者?”看看一些谈论 MVP 的网站,不太清楚 View 和演示者是否应该互相认识。
什么是最好的?
- 要求他们使用接口(interface)来消除循环?
- 要求从 View 中删除
presenter
并让 Presenter 直接处理用户交互? - 什么都不做,MVP 中的这些包之间通常存在循环
谢谢!
最佳答案
实际上,虽然演示者实现 [1] 现在需要 View (界面),但演示者界面通常不需要。
典型的模式是:
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)声明为嵌套在view接口(interface)中:
interface FooView extends IsWidget {
interface Presenter {
// ...
}
void setPresenter(Presenter presenter);
// ...
}
class FooPresenter extends AbstractActivity implements FooView.Presenter {
// ...
}
Wrt impls 了解 impls,最重要的是演示者 impl 不引用 View impl,因为它(通常)会阻止在没有 GWTTestCase
的情况下对其进行单元测试(模拟 View ) 。反之则问题不大,但与 impl 相比,您实际上并不需要演示者接口(interface),对吗?
[1] 从技术上讲,它可能是 View 实现,但通常是相反的,因此 View 可以比演示者更长寿(演示者通常是轻量级的,与 View 相反,由于 DOM, View 的创建时间可能不可忽略操纵)
关于java - View 和演示者之间的 MVP 和包循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12705687/