简体   繁体   English

GWT中的MVP模式:如何在Presenter中初始化Model / View和处理服务器请求?

[英]MVP Pattern in GWT: How to initialize Model/View and handle server requests in the Presenter?

This question isn't necessarily GWT bounded but on the other hand this comes right from my attempt to use it correctly. 这个问题不一定受GWT的限制,但是另一方面,这是我尝试正确使用它的结果。

I am using the MVP pattern ( as recommended ) in GWT but I am not sure how to deal with the model and the view as well as I am not quite sure how to create requests to the server. 我在GWT中使用MVP模式( 如推荐的那样 ),但是我不确定如何处理模型和视图,也不确定如何创建对服务器的请求。 In particular I would like to know 我特别想知道

  • Where do I initialize MyView ? 在哪里初始化MyView Does the presenter do that by itself in the constructor or does it receive a valid reference as parameter to the constructor? 演示者是在构造函数中自行执行此操作,还是接收到有效的引用作为构造函数的参数?
  • The same with MyModel . MyModel相同。 As the instance of MyModel might be shared among different presenters I guess it should be passes to the presenters constructor. 由于MyModel的实例可能会在不同的演示者之间共享,我想应该将其传递给演示者构造函数。
  • How do I make requests to the server in the presenter? 如何向演示者中的服务器发出请求? Do I have an additional layer that will handle my request or is it recommended to use MyServletAsync right there as well? 我是否还有一个额外的层来处理我的请求,还是建议在那里也使用MyServletAsync

I'm having a hard time figuring out a good design. 我很难确定一个好的设计。 See below an example code that shows how I am doing it now: 请参阅下面的示例代码,其中显示了我现在的操作方式:

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) {
        // ..
    }

}

Thank you for any advice. 感谢您的任何建议。

The MVP pattern is great, and it's designed to isolate but mediate totally different things. MVP模式很棒,它旨在隔离但可以调解完全不同的事物。 However, the pattern does not dictate how it's implemented and it's all on your own, but respecting some aspects, sure. 但是,该模式并不能决定如何实现它,而是完全由您自己决定,而是可以确保尊重某些方面。 Out of my experience, I would say that: 根据我的经验,我会说:

Where do I initialize MyView? 在哪里初始化MyView?

A presenter is better to accept some kind of a view factory (or a supplier in general as we can already hold an existing view, especially in a GWT case), and let the presenter decide when instantiate or accept the view. 演示者最好接受某种视图工厂(或一般来说是供应商,因为我们已经可以保存现有视图,尤其是在GWT情况下),然后让演示者决定何时实例化或接受视图。 My current project uses a small custom library that defines an abstract presenter and this is how it's implemented: 我当前的项目使用一个小的自定义库,该库定义了一个抽象演示者,这是如何实现的:

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

...

}

The main reason of passing the view factory is injecting the presenter to the view as views mostly should have references to their respective presenters (+ I prefer to have final fields, so this is a way of having both final references: presenter to view, and view to presenter). 通过视图工厂的主要原因是将演示者注入到视图中,因为视图大多应该引用其各自的演示者(+我更喜欢具有最终字段,因此这是同时具有两个最终引用的一种方式:演示者可以查看,并且查看演示者)。

I guess it should be passes to the presenters constructor. 我想应该将其传递给presenters构造函数。

Yes, it may be passed via a constructor like in the example above, however some people may prefer set-accessors like setModel and setView . 是的,它可以通过上面的示例中的构造函数进行传递,但是有些人可能更喜欢setModelsetView类的集合访问setView

How do I make requests to the server in the presenter? 如何向演示者中的服务器发出请求?

This is what model is for. 这就是模型的目的。 A presenter is only a mediator between a model and a view, and it's basically only responsible for user interaction in both directions. 演示者只是模型和视图之间的中介者,并且基本上只负责两个方向上的用户交互。 Consider your model is a way to access your application, as a model should not be considered a dummy "get/set fields" object. 考虑模型是访问应用程序的一种方式,因为模型不应被视为虚拟的“获取/设置字段”对象。 Model is an abstraction over service layers, network communication (can be an abstraction behind a service), data storage, or whatever your application has. 模型是服务层,网络通信(可以是服务背后的抽象),数据存储或应用程序所具有的任何东西的抽象。 Thus, your presenter just has to notify the model for getting or putting some data (from/to elsewhere respectively). 因此,您的演示者只需要通知模型以获取或放入一些数据(分别来自其他地方)。 Also this allows you to write fully abstract layers. 这也使您可以编写完全抽象的图层。 If you do unit testing, then you're in trouble for testing your presenter due to private final MyServletAsync myService = MyServlet.Util.getInstance(); 如果进行单元测试,则由于private final MyServletAsync myService = MyServlet.Util.getInstance();您将难以测试演示者private final MyServletAsync myService = MyServlet.Util.getInstance(); requiring the servlet to be up (a bad idea, right?). 要求servlet正常运行(不好的主意,对吧?)。 So if getXyzFromServer becomes a part of the model (I would say, then it might be named getXyz because the presenter does not really cares where the Xyz is fetched from), you can easily mock your model and just test the pure presenter. 所以,如果getXyzFromServer成为模型的一部分(我会说,那么它可能被命名为getXyz因为主持人并没有真正关心其中Xyz是牵强),你可以很容易地嘲笑你的模型,只是测试纯粹的主持人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM