MVP模式。如何减少代码重复?

时间:2012-05-13 17:46:39

标签: design-patterns gwt mvp gwt-mvp

MVP模式假设View向Presenter公开方法。例如,在View中我们可以写:

public HasClickhandlers getButton() {
    return myBtn;
} 

并从演示者访问此方法,例如

view.getButton().addclickhanlder() ...

但是当我以这种方式构建我的应用程序时,我有很多不必要的代码。例如,我想创建TablesViewTablesPresenter(我认为TablesPresenterTablesView是最小实体(最小模块),不能分为更小的演示者和意见,并不能更复杂)。然后,当我创建TablesView时,我想在此视图中添加另一个自定义组件 - MyCustomTable。在MyCustomTable内置MyCustomHeader,在MyCustomHeader内置MyCustomFilter等等(此序列可能会更长)... 问题是当我想从Presenter访问MyCustomFilter内的用户输入文本时,我需要在MyCustomFilter上公开方法:

//inside MyCustomFilter
public String getFilterText() {
   return textBox.getText();
}

然后在包含MyCustomFilter的小部件中 - 即在MyCustomHeader我需要公开此方法:

//inside MyCustomHeader
public String getFilterText() {
  return myCustomFilter.getFilterText();
}

之后,在MyCustomTable内我需要公开这个方法:

//inside MyCustomTable
public String getFilterText() {
  return myCustomHeader.getFilterText();
}

之后我需要在getFilterText()(包含TablesView)中公开MyCustomTable方法,在完成所有这些操作后,我的演示者可以访问MyCustomFilter内的文本。有时这个序列更长。 那么如何解决这个问题呢?可能我不明白有关MVP的一些事情?

2 个答案:

答案 0 :(得分:2)

您的视图无法在其中一个组件上返回视图,但您必须考虑组件化:这将打破封装,您的视图会暴露其内部结构。

另外,请记住,MVP中MVP最重要的好处之一就是您可以轻松地模拟您的视图并对演示者进行单元测试,而不会出现迟缓GWTTestCase。有一些权衡可以使您的代码易于测试/模拟。

答案 1 :(得分:1)

解决这个问题的一种方法是使用接口。通过这种方式,您可以公开组件的视图,而不会在视图和演示者之间创建紧密耦合。

这些方面的东西:

public interface CustomFilter {
   String getFilterText();
   // other methods that might be accessed from your presenter
}

public class MyCustomFilter implements CustomFilter {

    @Override
    public String getFilterText() {
        return textBox.getText();
    }
}

你可以为其他组件做同样的事情:

CustomHeader:

public interface CustomHeader {
   CustomFilter getFilter();
   // or String getFilterText()
   // other methods that might be accessed from your presenter
}

public class MyCustomHeader implements CustomHeader {

    @Override
    public CustomFilter getFilter() {
        return myCustomFilter;
    }
}

CustomTable:

public interface CustomTable {
   CustomHeader getHeader();
   // or Sring getFilterText();
   // other methods that might be accessed from your presenter
}

public class MyCustomTable implements CustomTable {

    @Override
    public CustomHeader getHeader() {
        return myCustomHeader;
    }
}

您可以决定是否只想在每个接口中公开String或整个客户端组件的接口。如果您公开整个界面,可能会在演示者中通过这样的调用来违反law of demeter

getView().getTable().getHeader().getFilter().getFilterText(). 

可能更好的解决方案是在您的界面中定义字符串,将层次结构中的调用委托给您的CustomFilter界面:getView().getTable().getFilterText();even getView().getFilterText()

使用界面的其他好处是您可以轻松地模拟它们以进行单元测试您的演示者甚至单独查看组件,您可以轻松地在UI组件的不同实现之间创建一个切换(例如,针对智能手机优化的一个)等,而不改变演示者中的任何内容