GWT中的MVP模式:如何初始化模型/视图并处理Presenter中的服务器请求? [英] MVP Pattern in GWT: How to initialize Model/View and handle server requests in the Presenter?

查看:130
本文介绍了GWT中的MVP模式:如何初始化模型/视图并处理Presenter中的服务器请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我使用的是MVP模式(

),这个问题不一定是GWT有界的,但另一方面, ),但我不确定如何处理模型和视图,以及我不太确定如何创建请求到服务器。特别是我想知道




  • 我在哪里初始化 MyView ?演示者是否自己在构造函数中完成它,或者它是否接收到作为构造函数参数的有效引用?

  • MyModel 相同。由于 MyModel 的实例可能会在不同的演示者之间共享,我猜它应该传递给演示者的构造函数。

  • 如何向演示者中的服务器发出请求?我是否有额外的图层可以处理我的请求,或者是否推荐在那里使用 MyServletAsync



我很难搞清楚一个好的设计。下面看一个示例代码,显示我现在是如何做的:

  public class MyPresenter实现MyView.MyPresenter 

private final MyServletAsync myService = MyServlet.Util.getInstance();

私人MyModel myModel;
私人MyView myView;

public MyPresenter(MyView myView,MyModel myModel){

this.myView = myView;
this.myModel = myModel;

//注册单击处理..

this.myView.getNextXyzButton.addClickHandler(
新clickHandler事件(){
@覆盖
public onClick(Event event){
requestXyz(this.myModel.getXyz()。getOffset()+ 1);
}
});

this.myView.getPrevisousXyzButton.addClickHandler(
新clickHandler事件(){
@覆盖
公众的onClick(事件事件){
requestXyz(这一点。 myModel.getXyz()。getOffset() - 1);
}
});

//用偏移量0初始化Xyz
requestXyz(0);
}

/ *
*我应该在演示者这里做这个还是应该为
*创建另一个处理请求的层?
* /
私人无效requestXyz(最终诠释byOffset){
myService.getXyzFromServer(byOffset,新的AsyncCallback< XyzDto>(){
@覆盖
公共无效的onSuccess (XyzDto结果){
updateModelWithResult(结果);
}
@覆盖
公共无效onFailure处(Throwable的捕获){
displayError(捕获);
}
});
}

private updateModelWithResult(Xyz result){
this.myModel.setXyz(result);
this.myView.displayXyz(result);
}

private displayError(Throwable caught){
// ..
}

}

感谢您的任何建议。

解决方案

< MVP模式非常好,它旨在隔离但调解完全不同的东西。然而,这种模式并没有说明它是如何实现的,它完全依赖于你自己,但是要尊重某些方面。根据我的经验,我会说:


我在哪里初始化MyView?


主持人最好接受某种视图工厂(或一般的供应商,因为我们已经可以拥有现有的视图,特别是在GWT的情况下),并让演示者决定当实例化或接受视图时。我目前的项目使用了一个小的自定义库,它定义了一个抽象的主持人,这就是它的实现方式:
$ b

  public abstract class AbstractPresenter< M extends IModel,V extends IView> 
实现IPresenter< M,V> {

私人最终M模型;
私人最终V视图;

protected AbstractPresenter(final M model,final IViewFactory< V,?super IPresenter< M,V>> viewFactory){
this.model = model;
view = viewFactory.createView(this);
}

...

}

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


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


是的,它可以像上面例子那样通过构造函数传递,但有些人可能更喜欢set-accessors,比如 setModel setView


如何向服务器发送请求主持人?

这是模型的用途。演示者只是模型和视图之间的中介,它基本上只负责在两个方向上的用户交互。考虑你的模型是一种访问你的应用程序的方式,因为模型不应该被认为是一个虚拟的get / set fields对象。模型是对服务层,网络通信(可以是服务背后的抽象),数据存储或任何应用程序的抽象。因此,您的演示者只需通知模型获取或放置一些数据(分别从/到别处)。这也允许你写完全抽象的图层。如果你做单元测试,那么你就麻烦了用于测试你的演讲,由于私人最终MyServletAsync为myService = MyServlet.Util.getInstance(); 要求的servlet将上升(一个坏主意,对吧?)。因此,如果 getXyzFromServer 成为模型的一部分(我会说,那么它可能被命名为 getXyz ,因为演示者会并不在意从哪里获取 Xyz ),您可以轻松地模拟您的模型,只需测试演示者。


This question isn't necessarily GWT bounded but on the other hand this comes right from my attempt to use it correctly.

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. In particular I would like to know

  • Where do I initialize 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. As the instance of MyModel might be shared among different presenters I guess it should be passes to the presenters constructor.
  • 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?

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. 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?

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. 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.

Yes, it may be passed via a constructor like in the example above, however some people may prefer set-accessors like setModel and 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(); requiring the servlet to be up (a bad idea, right?). 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.

这篇关于GWT中的MVP模式:如何初始化模型/视图并处理Presenter中的服务器请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆