GWT MVP
建立任何大规模的应用都有其障碍,GWT的应用程序也不例外。多个开发者基于同样的代码并行开发,往往会让代码变得混乱,难于维护。为了帮助理清头绪,我们介绍设计模式到我们的项目中。
有各种各样的设计模式供我们选择:Presentation-abstraction-control, Model-view-controller, Model-view-presenter等等。每种设计模式都有自己的优点,但是我们发现Model-view-presenter (MVP)这种模式最适合GWT。原因有二:
- MVP模式允许多个开发者共同开发,互不影响
- MVP模式使我们能够减少使用GWTTestCase,这依赖于浏览器的存在;而且,对于大部分的代码,只需要写的轻量级(快速)的JRE测试(不需要浏览器支持)
简单的例子
一旦理解了MVP的基本原理,创建一个基于MVP的应用将会变得非常容易。为了帮助理解,这里提供了一个简单的应用Contacts作为例子。
在开始之前,要先介绍一下基本组件:
Model
模型包含了业务对象,在本例中,有
- Contact:联系人,包含了姓名、email等信息
- ContactDetails:Contact的轻量版本,仅仅包含了唯一标识和显示名。更少的序列化和传输会让联系人列表检索效率更高
View
视图包含了所有的UI组件,负责UI组件的布局。它没有Model的概念,就是说它并不知道它将要展示的是Contact联系人列表。
本例中,视图有
- ContactsView:显示联系人列表
- EditContactView:用来添加或者编辑联系人
Presenter
Presenter包含了本例中所有的逻辑,如历史管理、视图转换、数据同步等。一个普遍的规则是,对每一个视图,都需要一个Presenter来控制视图和处理事件Event。
本例中,包含
- ContactsPresenter
- EditContactPresenter
可以看到Presenter与View是一一对应的。
整个示例工程的结构如下:
接下来,我们来看看这些组件是如何进行交互的。
绑定Presenter和View
先看看示例中ContactView的界面
该视图有三个组件,两个按钮和一个表格。对应的Presenter需要做
- 响应按钮点击事件
- 用数据填充列表
- 响应列表点击事件
- 查询被选中的联系人信息
在ContactsPresenter中,定义一个Display的接口
方法setData()用来获取Model数据到View,而无需关心Model的内部结构。这样的优点在于当Model发生变化的时候,不用修改View的代码。我们来看看它是如何获取服务端的数据:
监听UI的事件:
响应UI上面的操作,例如删除选中的记录:
再次申明,为了充分了解MVP的优点,Presenter应该不认识任何基础组件代码。只要把View封装在Display的接口中,这样鱼和熊掌都可兼得,一方面减少了GWT各组件之间的联系,另一方面依然可以实例化一个Display对象到面板上。
Events and the Event Bus