GWT中的MVP模式:如何初始化模型/视图并在Presenter中处理服务器请求?

时间:2015-08-21 17:26:49

标签: java gwt mvp

这个问题不一定是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) {
        // ..
    }

}

感谢您的任何建议。

1 个答案:

答案 0 :(得分:2)

MVP模式非常棒,它旨在孤立但调解完全不同的东西。然而,这种模式并没有决定它是如何实现的,而是一切都靠你自己,但尊重某些方面,当然。根据我的经验,我会说:

  

我在哪里初始化MyView?

演示者最好接受某种视图工厂(或者通常是供应商,因为我们已经可以保存现有视图,尤其是在GWT情况下),并让演示者决定何时实例化或接受视图。我当前的项目使用一个小的自定义库来定义一个抽象的演示者,这就是它的实现方式:

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);
    }

...

}

传递视图工厂的主要原因是将视图注入到视图中,因为视图主要应该引用它们各自的演示者(+我更喜欢有最终字段,所以这是两种最终引用的方式:演示者到查看和查看演示者)。

  

我想它应该传递给演示者构造函数。

是的,它可以通过上面示例中的构造函数传递,但有些人可能更喜欢setModelsetView等集合访问器。

  

如何在演示者中向服务器发出请求?

这就是模型的用途。演示者只是模型和视图之间的中介,它基本上只负责两个方向的用户交互。考虑您的模型是访问您的应用程序的一种方式,因为模型不应被视为虚拟的“获取/设置字段”对象。模型是服务层,网络通信(可以是服务背后的抽象),数据存储或应用程序所具有的任何内容的抽象。因此,您的演示者只需通知模型获取或放置一些数据(分别来自/到其他地方)。这也允许您编写完全抽象的图层。如果您进行单元测试,那么由于private final MyServletAsync myService = MyServlet.Util.getInstance();要求servlet启动(因为一个坏主意,对吧?),您在测试演示者方面遇到了麻烦。因此,如果getXyzFromServer成为模型的一部分(我会说,那么它可能被命名为getXyz,因为演示者并不真正关心从哪里获取Xyz),您可以轻松地嘲笑你的模型,然后测试演示者。