GWT 中的 MVP 模式:如何在 Presenter 中初始化 Model/View 和处理服务器请求?
MVP Pattern in GWT: How to initialize Model/View and handle server requests in the Presenter?
这个问题不一定是 GWT 限制的,但另一方面,这是我尝试正确使用它的结果。
我在 GWT 中使用 MVP 模式(推荐),但我不确定如何处理模型和视图,也不太确定如何处理创建对服务器的请求。我特别想知道
- 我在哪里初始化
MyView
?演示者是在构造函数中自己执行此操作,还是接收到一个有效引用作为构造函数的参数?
- 同
MyModel
。由于 MyModel
的实例可能在不同的演示者之间共享,我想它应该传递给演示者构造函数。
- 如何在演示器中向服务器发出请求?我是否有一个额外的层来处理我的请求,还是建议也在那里使用
MyServletAsync
?
我很难找到一个好的设计。请参阅下面的示例代码,展示我现在是如何做的:
public class MyPresenter implements MyView.MyPresenter
private final MyServletAsync myService = MyServlet.Util.getInstance();
private MyModel myModel;
private MyView myView;
public MyPresenter(MyView myView, MyModel myModel) {
this.myView = myView;
this.myModel = myModel;
// Register click handler ..
this.myView.getNextXyzButton.addClickHandler(
new ClickHandler() {
@Override
public onClick(Event event) {
requestXyz(this.myModel.getXyz().getOffset() + 1);
}
});
this.myView.getPrevisousXyzButton.addClickHandler(
new ClickHandler() {
@Override
public onClick(Event event) {
requestXyz(this.myModel.getXyz().getOffset() - 1);
}
});
// Initialize Xyz with offset 0
requestXyz(0);
}
/*
* Should I do this here in the presenter or should I
* create another layer that handles requests?
*/
private void requestXyz(final int byOffset) {
myService.getXyzFromServer(byOffset, new AsyncCallback<XyzDto>() {
@Override
public void onSuccess(XyzDto result) {
updateModelWithResult(result);
}
@Override
public void onFailure(Throwable caught) {
displayError(caught);
}
});
}
private updateModelWithResult(Xyz result) {
this.myModel.setXyz(result);
this.myView.displayXyz(result);
}
private displayError(Throwable caught) {
// ..
}
}
感谢您的任何建议。
MVP 模式很棒,它旨在隔离但调解完全不同的事物。然而,该模式并没有规定它是如何实现的,它完全取决于你自己,但肯定会尊重某些方面。根据我的经验,我会说:
Where do I initialize MyView?
presenter 最好接受某种视图工厂(或者一般的供应商,因为我们已经可以持有现有视图,尤其是在 GWT 情况下),并让 presenter 决定何时实例化或接受视图.我当前的项目使用一个小型自定义库,它定义了一个抽象演示者,它是这样实现的:
public abstract class AbstractPresenter<M extends IModel, V extends IView>
implements IPresenter<M, V> {
private final M model;
private final V view;
protected AbstractPresenter(final M model, final IViewFactory<V, ? super IPresenter<M, V>> viewFactory) {
this.model = model;
view = viewFactory.createView(this);
}
...
}
传递视图工厂的主要原因是将演示者注入视图,因为视图大多应该引用它们各自的演示者(+我更喜欢有最终字段,所以这是一种同时拥有最终引用的方式:演示者查看,并查看演示者)。
I guess it should be passes to the presenters constructor.
是的,它可以像上面的例子一样通过构造函数传递,但是有些人可能更喜欢像 setModel
和 setView
.
这样的设置访问器
How do I make requests to the server in the presenter?
这就是模型的用途。 Presenter 只是模型和视图之间的中介,它基本上只负责双向的用户交互。考虑您的模型是访问您的应用程序的一种方式,因为模型不应被视为虚拟 "get/set fields" 对象。模型是对服务层、网络通信(可以是服务背后的抽象)、数据存储或您的应用程序具有的任何东西的抽象。因此,您的演示者只需通知模型获取或放置一些数据(分别在其他地方 from/to)。这也允许您编写完全抽象的层。如果您进行单元测试,那么由于 private final MyServletAsync myService = MyServlet.Util.getInstance();
需要启动 servlet(这是个坏主意,对吧?),因此您在测试演示者时遇到了麻烦。因此,如果 getXyzFromServer
成为模型的一部分(我会说,那么它可能被命名为 getXyz
因为演示者并不真正关心 Xyz
从哪里获取),您可以轻松地模拟您的模型并测试 pure 演示者。
这个问题不一定是 GWT 限制的,但另一方面,这是我尝试正确使用它的结果。
我在 GWT 中使用 MVP 模式(推荐),但我不确定如何处理模型和视图,也不太确定如何处理创建对服务器的请求。我特别想知道
- 我在哪里初始化
MyView
?演示者是在构造函数中自己执行此操作,还是接收到一个有效引用作为构造函数的参数? - 同
MyModel
。由于MyModel
的实例可能在不同的演示者之间共享,我想它应该传递给演示者构造函数。 - 如何在演示器中向服务器发出请求?我是否有一个额外的层来处理我的请求,还是建议也在那里使用
MyServletAsync
?
我很难找到一个好的设计。请参阅下面的示例代码,展示我现在是如何做的:
public class MyPresenter implements MyView.MyPresenter
private final MyServletAsync myService = MyServlet.Util.getInstance();
private MyModel myModel;
private MyView myView;
public MyPresenter(MyView myView, MyModel myModel) {
this.myView = myView;
this.myModel = myModel;
// Register click handler ..
this.myView.getNextXyzButton.addClickHandler(
new ClickHandler() {
@Override
public onClick(Event event) {
requestXyz(this.myModel.getXyz().getOffset() + 1);
}
});
this.myView.getPrevisousXyzButton.addClickHandler(
new ClickHandler() {
@Override
public onClick(Event event) {
requestXyz(this.myModel.getXyz().getOffset() - 1);
}
});
// Initialize Xyz with offset 0
requestXyz(0);
}
/*
* Should I do this here in the presenter or should I
* create another layer that handles requests?
*/
private void requestXyz(final int byOffset) {
myService.getXyzFromServer(byOffset, new AsyncCallback<XyzDto>() {
@Override
public void onSuccess(XyzDto result) {
updateModelWithResult(result);
}
@Override
public void onFailure(Throwable caught) {
displayError(caught);
}
});
}
private updateModelWithResult(Xyz result) {
this.myModel.setXyz(result);
this.myView.displayXyz(result);
}
private displayError(Throwable caught) {
// ..
}
}
感谢您的任何建议。
MVP 模式很棒,它旨在隔离但调解完全不同的事物。然而,该模式并没有规定它是如何实现的,它完全取决于你自己,但肯定会尊重某些方面。根据我的经验,我会说:
Where do I initialize MyView?
presenter 最好接受某种视图工厂(或者一般的供应商,因为我们已经可以持有现有视图,尤其是在 GWT 情况下),并让 presenter 决定何时实例化或接受视图.我当前的项目使用一个小型自定义库,它定义了一个抽象演示者,它是这样实现的:
public abstract class AbstractPresenter<M extends IModel, V extends IView>
implements IPresenter<M, V> {
private final M model;
private final V view;
protected AbstractPresenter(final M model, final IViewFactory<V, ? super IPresenter<M, V>> viewFactory) {
this.model = model;
view = viewFactory.createView(this);
}
...
}
传递视图工厂的主要原因是将演示者注入视图,因为视图大多应该引用它们各自的演示者(+我更喜欢有最终字段,所以这是一种同时拥有最终引用的方式:演示者查看,并查看演示者)。
I guess it should be passes to the presenters constructor.
是的,它可以像上面的例子一样通过构造函数传递,但是有些人可能更喜欢像 setModel
和 setView
.
How do I make requests to the server in the presenter?
这就是模型的用途。 Presenter 只是模型和视图之间的中介,它基本上只负责双向的用户交互。考虑您的模型是访问您的应用程序的一种方式,因为模型不应被视为虚拟 "get/set fields" 对象。模型是对服务层、网络通信(可以是服务背后的抽象)、数据存储或您的应用程序具有的任何东西的抽象。因此,您的演示者只需通知模型获取或放置一些数据(分别在其他地方 from/to)。这也允许您编写完全抽象的层。如果您进行单元测试,那么由于 private final MyServletAsync myService = MyServlet.Util.getInstance();
需要启动 servlet(这是个坏主意,对吧?),因此您在测试演示者时遇到了麻烦。因此,如果 getXyzFromServer
成为模型的一部分(我会说,那么它可能被命名为 getXyz
因为演示者并不真正关心 Xyz
从哪里获取),您可以轻松地模拟您的模型并测试 pure 演示者。