GWT MVP架构的优势

7
我正在学习GWT,并且在多个地方阅读到使用MVP架构开发GWT应用程序是最合适的。我还了解到,使用MVP ARCH进行测试很容易。有人能解释一下为什么使用MVP架构进行测试很容易吗?
此外,我正在使用MVP开发项目,但我觉得连接数据库非常繁琐。我的意思是,为了连接数据库,我必须更新我的Presenter、Service、ServiceAsync、ServiceImpl和Facades。
因此,有人能为我提供GWT中MVP的精髓吗?我会感激几个例子。
2个回答

23

将展示器(包含逻辑)和视图(UI控件的简单包装器)分离可以让您:

  • 编写展示器的单元测试,无需运行对应的环境(桌面,浏览器,GWT小部件)。
  • 重用前端逻辑,而无需绑定特定的小部件/UI框架。

后一种用例很少见,因此让我们专注于MVP模型适用于自动化程序化测试。对于开发团队来说,通常采用持续构建/测试周期的形式进行,使用Hudson(或类似工具)在无头服务器上运行,这样每次运行测试时就不必打开Web浏览器、创建控件等操作。

MVP+GWT的典型用法是,视图实现由展示器提供的接口,并且通常该接口是根据其他通用接口定义的。下面是一个非常简单的展示器示例,当单击按钮时它会增加一个数字标签——请注意,视图并没有直接暴露TextBoxButton,而是返回通用的HasTextHasClickHandlers实例:

public class ButtonClickPresenter {
    public interface View {
        HasText currentValue();
        HasClickHandlers incrementButton();
    }

    private final View myView;
    private int currentValue = 0;

    public ButtonClickPresenter(View myView) {
        this.myView = myView;
        this.myView.currentValue().setText("0");

        this.bind(); // for the sake of demonstration
    }

    public void bind() {
        this.myView.incrementButton.addClickHandler(
            @Override
            new ClickHandler() {
                void onClick(ClickEvent event) {
                    currentValue ++;
                    myView.currentValue().setText(
                        Integer.toString(currentValue));
                }
            });
    }
}

“真实”的视图返回UI小部件(在此示例中通过UiBinder创建):

public class ButtonClickView implements ButtonClickPresenter.View {
    // ... skipped UiBinder initialisation ...

    @UiField Label currentValueLabel;
    @UiField Button incrementButton;

    @Override
    public HasText currentValue() {
        return currentValueLabel;
    }

    @Override
    public HasClickHandlers incrementButton() {
        return incrementButton;
    }

    // ... etc ...
}

而单元测试则创建了一个虚构的实现(或使用MockitoEasyMock等)因此不需要任何UI组件:

public class ButtonClickPresenterTest {
    ButtonClickPresenter presenter;
    ClickHandler currentHandler;
    String currentText;

    @Before
    public void setUp() {
        presenter = new ButtonClickPresenter(
            // dummy view - just stores label text in a String and
            // keeps track of the Presenter's click handler
            new ButtonClickPresenter.View() {
                @Override
                public HasText currentValue() {
                    return new HasText() {
                        @Override public String getText() { return currentText; }
                        @Override public void setText(String text) { currentText = text; }
                    };
                }

                @Override
                public HasClickHandlers incrementButton() {
                    return new HasClickHandlers() {
                        @Override
                        public HandlerRegistration addClickHandler(ClickHandler handler) {
                            currentHandler = handler;
                        }
                    };
                }
            });
    }

    @Test
    public void testIncrement() {
        // initial value
        assertEquals("0", currentText);

        // clicking the button should increment the number
        currentHandler.onClick(null);
        assertEquals("1", currentText);
    }
}

关于你接下来的段落:你的视图根本不应该连接到数据库!Presenter 应该通过 Service/ServiceAsync(或抽象类,如 gwt-dispatchgwt-platform)请求数据,然后调用视图上的方法来填充 UI。

顺便说一下,如果你正在寻找 GWT MVP 代码示例,最后两个链接(连同 gwt-presenter)是一个很好的开始 - 结合 Google GIN,它们提供了将所有这些东西绑定在一起的框架。

说了这么多,我同意 - GWT+MVP+Java 的组合可能会让人感到困难和非常冗长(我很高兴现在不必经常使用它)。然而,另一种选择更加没有吸引力:一个无法进行测试和维护的混乱代码块...


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接