要介绍MVP,MVVM,我们不得不提 MVC 框架,因为 MVC 是最早出现的软件设计典范,其他的都是在此基础上迭代更新而来的,各有优势,适用的场景各有不同,但他们的共同点是他们的目的都是为了复用代码。
注意: 这些架构模式跟设计模式是两种不同的东西。
MVC架构
MVC 的概念最早出现在二十世纪八十年代的 施乐帕克 实验室中(就是那个发明图形用户界面和鼠标的实验室),当时施乐帕克为 Smalltalk 发明了这种软件设计模式。
Model 模型
模型表示抽象数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用像 Hibernate 这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。良好的 Model 能很好的复用在各种 View 视图中
View 视图
视图是用户看到并与之交互的界面。对Web应用程序来说,视图就是由HTML元素组成的界面。对于Android则是 Activity 和布局文件构成的 UI 界面
Controller 控制器
控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当用户操作 View 视图发起请求,如登录请求等等,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据。
最典型的MVC就是JSP + servlet + JavaBean的模式。
MVP
Model-View-Presenter 的简称。 MVP 是从经典的模式 MVC 演变而来,它们的基本思想有相通的地方:Controller/Presenter 负责逻辑的处理,Model 提供数据,View 负责显示。
和MVC不同的是,MVP 里的 Presenter 层会定义一个协议 Contract, 抽象出View层里会调用的接口, 比如查询数据等等,封装到 Presenter 接口里,以及抽象出 具体的 Presenter 实现中,需要调用的 UI 操作,比如查询完数据要将数据回传给 View 层
简单的伪代码例子,
// 在 Contract 里,定义好 Presenter 接口和 View 相关接口
public interface ListDataContract {
interface ListDataView extends BaseView {
// 填充数据
void fillData(List<Item> obj);
}
interface Presenter extends BasePresenter {
// 返回指定数据
boolean queryData();
}
}
在 View 里使用
public class MainActivity extends BaseActivity implements ListDataContract.ListDataView {
ListDataContract.Presenter mPresenter;
void init() {
...
mPresenter.getData();
...
}
void fillData(List<Item> obj) {
// 更新 UI
}
}
而实际的 Presenter 实现,
public class ListPresenter implements ListDataContract.Presenter {
ListDataContract.ListDataView mView;
boolean getData() {
// 通过 model 获取数据
List<Item> data = model.queryData();
// 更新到视图里
mView.fillData(data);
}
}
可以看出, MVP 很好的将 View 和 Model 分开,解耦效果出众。 如果我们的 Presenter 定义良好,就可以达到很好的复用代码效果,不仅 model 层可以复用, 就连 Precenter 层也可以复用, 这也是 MVP 和 MVC 很大的一个区别之处,因为 MVC 里的 Controller 很难达到复用的效果。 还有一个优点是,不需要引入很多的其他框架就可以使用
不过 MVP 的缺点也比较明显, 就是需要创建大量的 Contract 接口类
MVVM
MVVM 是 Model-View-ViewModel 的简写。
MVVM 在使用当中,通常还会利用双向绑定技术,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel 变化时,View 也会自动变化。所以,MVVM 模式有些时候又被称作:model-view-binder 模式。
在理解了 MVP 之后,MVVM 其实是在 MVP 的基础上演变而来的,功能基本相同,因此 ViewModel 其实就是相当于 MVP 里的 Presenter,用于将 View 和 Model 解耦。不同的是, MVVM 采用的是 数据绑定技术,或者数据的双向绑定技术。ViewModel 通常要实现一个 observer 观察者,当数据发生变化,ViewModel 能够监听到数据的这种变化,然后通知到对应的视图做自动更新。而当用户操作视图,ViewModel 也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且 MVVM 中的 View 和 ViewModel 可以互相通信。MVVM 流程图如下:
推荐Google 官网的 Android MVVM 组件
Architecture Components
MVVM 的作用和问题
MVVM 在实际使用中,确实能够使得 Model 层和 View 层解耦,但是如果你需要实现 MVVM 中的双向绑定的话,那么通常就需要引入更多复杂的框架来实现了。
对此,MVVM 的作者 John Gossman 的批评应该是最为中肯的。John Gossman 对 MVVM 的批评主要有两点:
数据绑定使得 Bug 很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。
对于过大的项目,数据绑定需要花费更多的内存。
某种意义上来说,我认为就是数据绑定使得 MVVM 变得复杂和难用了。但是,这个缺点同时也被很多人认为是优点。