分析 MVX 架构模式及其运用

在软件开发过程中,好的架构设计能显著提高软件开发的效率,这在 Android 开发中同样如此。到目前为止,有三种被广泛使用的架构设计模式,即:MVC、MVP、MVVM。网上有很多介绍他们的文章,但内容参差不齐,本篇将介绍大众对他们的主流理解,并加以实例说明。

1 MVC

1.1 概念

Controller(控制器):负责调度事件,并通知 Model 操作数据。
View(视图):负责显示界面,并将用户事件通知给控制器。
Model(数据模型):Model 是数据以及和数据相关的业务逻辑。比如 Controller 通知 Model 将数据作加 1 处理,这个加 1 的操纵应该在 Model 中完成。如果需要显示到界面的话,还需要 Model 通知 View 更新界面。

刷新界面的分工问题
上面讲到的 Model 通知 View 刷新界面是 MVC 模式中一种刷新界面的方式,但也有通过 Controller 直接刷新界面的情况(如:Activity), 并且网上把这种情况也归为 MCV 操作的一部分。这里不讨论对错,只是大家要清楚 MVC 可以有这些情况,而且它的概念边界模糊,具体场景出现时,能够分辨的出它的存在即可。

1.2 例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class MvcDemo {
class Model {
View view;
int data;

void processData() {
//处理数据。
data++;
//通知 View 显示数据。
view.showData(data);
}
}

class View {
Controller controller;

void clicked() {
//产生 click 事件,并通知 Controller 处理。
controller.viewClicked();
}

void showData(int data) {
//显示数据。
...
}
}

class Controller {
Model model;

void viewClicked() {
//接收到事件后,通知 Model 处理数据。
model.processData();

//特别地,Android 的 Activity 在这里直接控制界面的显示了。
}
}
}

1.3 缺点

不仅 Model 和 View 之间有联系,同时 Controller 有时也会控制 View 的显示,如 Android 中的 Activity Controller 既负责通知 Model 操作数据,又可以负责界面显示,Controller 和 View 的代码耦合性太高。

2 MVP

2.1 概念

Presenter(控制器):负责调度事件,并通知 Model 操作数据,数据更新后再通知 View 显示数据。
View(视图):负责显示界面,并将用户事件通知给调度器。
Model(数据模型):Model 是数据以及和数据相关的业务逻辑。比如 Presenter 通知 Model 将数据作加 1 处理,这个加 1 的操纵应该在 Model 中完成。

2.2 例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class MvpDemo {
class Presenter {
private Iview view;

public Presenter(Iview view) {
this.view = view;
}

public void load() {
//通知 model 操作数据。
Model model = new Model();
model.processData();
//通知 View 显示数据。
view.showData(model.data);
}
}

class Model {
int data;

void processData() {
//处理数据
data++;
}
}

class View implements Iview {
@Override
public void showData(int data) {
//显示数据
}
}

interface Iview {
void showData(int data);
}
}

可以看到,MVP 将 Model 和 View 分离了,同时最重要的是它把界面的显示完全交给 View 来完成了。

讲到这里,大家可以看到 Android 的 MVC 模式的弊端就是因为 Controller(Activity) 和 View 被耦合在一起了,傻傻分不清楚,所以 MVP 最大的贡献就是把 Controller 和 View 彻底分离,让他们各自负责自己应该负责的。其实,如果我们在 MVC 模式的使用过程中,将控件自定义化,每个控件提供依据数据刷新 UI 的方法,这样也是可以让 View 和 Controller 各自负责自己的工作的。

2.3 优缺点

优点:
1、结构清晰,职责划分清晰。
2、模块间充分解耦。
3、有利于组件的重用。

缺点:
1、会引入大量的接口,导致项目文件数量激增。
2、增大代码结构复杂性。

3 MVVM

3.1 概念

MVVM 是加了数据绑定功能的 MVP。

ViewModel(控制器):负责双向绑定 View 和 Model,同时通知 Model 操作数据。
View(视图):负责显示界面。
Model(数据模型):Model 是数据以及和数据相关的业务逻辑。比如 ViewModel 通知 Model 将数据作加 1 处理,这个加 1 的操纵应该在 Model 中完成。

3.2 例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MvvmDemo {
class ViewModel {
ObjectAttr data = new ObjectAttr();

public ViewModel(View view) {
//实现 View 和 Model 之间双向绑定。
Utils.binder(view, data);
}

public void load() {
//通知 model 处理数据,并获取处理后的数据。
Model model = new Model();
ObjectAttr objectAttr = model.processData();
//更新数据,之后视图会自动刷新。
data.setData(objectAttr);
}

}

class Model {
private ObjectAttr data;

public ObjectAttr processData() {
//处理数据。
data = new ObjectAttr();
return data;
}
}
}

3.3 优缺点

优点:
1、结构清晰,职责划分清晰。
2、模块间充分解耦。
3、在 MVP 的基础上,MVVM 把 View 和 ViewModel 也进行了解耦。

缺点:
1、Debug 困难,由于 View 和 ViewModel 解耦,导致 Debug 时难以一眼看出 View 的事件传递。
2、代码复杂性增大。

4 总结

传统意义上 MVC 和 MVP 最大的区别是 View 和 Model 之间是否关联的区别。Android 中的 MVC 模式与传统 MVC 有很大的不同之处,表现在 Controller(Activity) 错误负责了 View 和 Model 本应该负责的工作,导致 Controller 代码结构变得复杂。

MVP 很好的解决了各个层之间过度依赖的关系,明确了每个层的职责,即:View 只负责展示数据,Model 只负责数据处理,Presenter 则只为 View 和 Model 之间的沟通提供桥梁。

MVVM 本质意义上并不算的上一种独立的架构模式,它只是在 MVP 基础上加上了数据绑定的功能,这样就将原来 Presenter 与 View 之间的交互也解耦了。数据绑定功能的实现可以使用 DataBinding。

DataBinding 的学习可以参考 这篇文章

如需了解 DataBinding 在 RecyclerView 中的使用请参考以下两篇文章:
文章1
文章2


参考资料

1、扔物线老师的 Hencoder plus 课程。
2、Android 开发中的架构模式。