GWT:使用单独的mvp构建小部件

时间:2011-09-19 23:36:02

标签: java design-patterns gwt widget mvp

我正在尝试使用分离的模型,视图和演示者构建gwt小部件。

到目前为止,我只使用了一个类用于所有这些组件:

一个紧凑的例子:

public class MyCellSelectableTable extends Composite {

   private WhatEverRepresentation selectedCell;

   public MyCellSelectableTable() {

      Grid myTable = new Grid(2,2);
      /*
       * Some code to realize a table with cell selection
       * ...
       */

     initWidget(myTable);
  }
}

在我看来,“selectedCell”(以及我项目中的许多其他数据)的信息应该存储在一个单独的模型中。 我怎样才能在结构上正确实现这一点,所以它仍然是一个小部件但是有一个封装的mvp架构?

3 个答案:

答案 0 :(得分:2)

在我的一个项目中,我被要求设计一个旋转项目,该项目在移动网络应用程序上看起来很好看。然后我们意识到我们实际上需要另一个我们的旋转器视图,它也是“更薄”的。所以我试图将MVP方法应用于我的小部件实现,这对我来说很有用。下面这个是一个非常简单的例子,不仅仅是为了演示而用于生产

以MVP模式定义Presenter和View界面。这里的要点是使视图实现变得愚蠢,以便可以毫不费力地切换它们。请注意,Spinner实际上并不是一个Widget,但它实现了IsWidget,这意味着它将被视为一个小部件,但事实上我们将传递视图实现的引用。

public class Spinner implements IsWidget, SpinnerPresenter{
    interface View{
        Widget asWidget();
        void stepUp(int step);
        void stepDown(int step);
        void setValue(int value);
        void setPixelSize(int width,int height);
    }   
    View view;
    int value;  
    public Spinner() {
        view = new SpinnerImpl(this);
        view.setValue(0);
    }   
    public int getValue() {
        return value;
    }   
    public void setValue(int value) {
        if (value == this.value)
            return;
        this.value = value;
        view.setValue(value);
    }
    public void setPixelSize(int width, int height){
        view.setPixelSize(width,height);
    }
    @Override
    public void downButtonClicked() {
        value--;
        view.stepDown(1);
    }
    @Override
    public void upButtonClicked() {
        value++;
        view.stepUp(1);
    }
    @Override
    public Widget asWidget() {
        return view.asWidget();
    }
}

视图实现本身实现了Spinner类中定义的视图接口。请注意我们如何将用户事件委托给Spinner类,以便通过SpinnerPresenter接口进行处理。

public class SpinnerImpl extends Composite implements Spinner.View{
    private TextBox txtBox;
    private Button upButton,downButton;
    private HorizontalPanel panel;
    private SpinnerPresenter presenter;
    public SpinnerImpl(SpinnerPresenter presenter){
        this.presenter = presenter;
        upButton = new Button("up");
        downButton = new Button("down");

        txtBox = new TextBox();
        txtBox.setEnabled(false);

        panel = new HorizontalPanel();
        panel.add(upButton);
        panel.add(txtBox);
        panel.add(downButton);

        addHandlers();
        initWidget(panel);      
    }   
    private void addHandlers() {
        upButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                presenter.upButtonClicked();
            }
        });
        downButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                presenter.downButtonClicked();
            }
        });     
    }
    @Override
    public void stepDown(int step) {
        txtBox.setValue(Integer.parseInt(txtBox.getValue())-1+"");
    }
    @Override
    public void stepUp(int step) {
        txtBox.setValue(Integer.parseInt(txtBox.getValue())+1+"");
    }
    @Override
    public void setValue(int value) {
        txtBox.setValue(0+"");
    }
}

SpinnerPresenter界面:

public interface SpinnerPresenter {
    void upButtonClicked();
    void downButtonClicked();
}

最后将我的小部件添加到rootpanel。请注意,我可以添加微调器类,就好像它是一个小部件

Spinner s = new Spinner();
RootPanel.get().add(s);

现在,如果我想改变我的微调器项目的外观,改变方向,可能为旋转等添加一个奇特的动画,我只需要更改我的View实现。最后但并非最不重要的是,在测试我的小部件时,这种方法将有所帮助,因为我可以轻松地模拟我的视图。

答案 1 :(得分:0)

我建议您阅读以下MVP文章,如果您还没有(如果有的话,请原谅我): http://code.google.com/webtoolkit/articles/mvp-architecture.html http://www.gwtproject.org/articles/mvp-architecture.html

请相信我,继续将您的模型,视图和演示者分开是值得的。这个问题在一个课程中似乎总是很简单,但是当我尝试过时,我总是把事情分开。您会感谢您更好地分离关注点和提供的灵活性。

答案 2 :(得分:0)

仅供参考,GWT中的单元小部件是在内部使用MVP构建的。 CellList(例如)是“视图”部分并实例化内部演示者。

此外,Google I / O 2010的这次会议让我大开眼界:http://www.google.com/events/io/2010/sessions/gwt-continuous-build-testing.html