一、MVC(Model‑View‑Controller)
角色职责
- Model 模型:数据层,负责数据、业务逻辑、数据库、网络请求。不关心界面。
- View 视图:UI 界面,展示数据,接收用户输入。
- Controller 控制器:中间人,接收 View 事件,调用 Model 处理业务,再通知 View 更新界面。
执行流程
- 用户操作 View
- View 将事件交给 Controller
- Controller 操作 Model 获取 / 修改数据
- Model 更新完成,通知 Controller
- Controller 去更新 View
经典 MVC 关系图
View <--> Controller <--> Model
- View 和 Model不直接通信,全部经过 Controller 中转。
实际开发变种(Android 老式 MVC)
Android 中 Activity/Fragment 既充当 Controller,又承担 View,Controller 和 View 高度耦合,这是 Android MVC 最大痛点。
MVC 优点
- 概念简单,上手容易
- Model 独立,可复用
- 职责初步拆分
MVC 缺点
- Controller 臃肿,大量逻辑堆在 Controller,容易形成大 Activity / 大 Controller
- View 强依赖 Controller,View 不好独立单元测试
- 耦合高,视图改动会修改 Controller 代码
二、MVP(Model‑View‑Presenter)
为了解决 MVC 中 Controller 臃肿、View 与 Controller 耦合而诞生。
角色职责
- Model:和 MVC 一致,数据、业务、网络数据库。
- View :接口抽象,定义 UI 要做什么;具体页面实现这个接口。View 只做 UI 渲染,不处理业务。
- Presenter:替代 Controller,业务逻辑全部放在 Presenter。持有 View 接口引用,调用 View 接口方法更新 UI。
关键点:View 是接口,Presenter 依赖 View 接口,不依赖具体页面。
执行流程
-
用户操作 View
-
View 回调给 Presenter
-
Presenter 调用 Model 处理数据
-
Model 返回结果给 Presenter
-
Presenter 调用 View 接口 更新界面
View <--> Presenter <--> Model
- Model 完全不知道 Presenter;
- Presenter 持有 View 接口;
- View 不能直接访问 Model。
MVP 优点
- 业务逻辑全部剥离到 Presenter,Activity/Fragment 只做 View 实现,代码清爽
- Presenter 依赖 View 接口,非常方便单元测试,Mock View 即可测试业务
- View、Model 解耦,视图可以替换
MVP 缺点
- 接口爆炸:每一个 UI 动作都要定义 View 接口,模板代码多
- Presenter 持有 View 引用,容易发生内存泄漏(页面销毁,Presenter 还持有 View)
- Presenter 依然会随着业务膨胀变庞大
内存泄漏问题:页面退出必须断开 Presenter 对 View 的引用。
三、MVVM(Model‑View‑ViewModel)
MVVM 核心创新:数据双向绑定,消除大量手动调用 UI 更新的代码。
角色职责
- Model:同上,数据、业务逻辑。
- View:UI 视图(页面、xml、模板),只负责展示。
- ViewModel :视图模型。保存视图状态、暴露可观察的数据,处理业务;不持有 View 的引用。
ViewModel 向外提供可观察的数据源,View 绑定这些数据;数据变,UI 自动刷新。
执行流程
-
用户操作 View,通过双向绑定自动修改 ViewModel 中的数据
-
ViewViewModel 调用 Model 执行业务、网络
-
Model 返回数据,更新 ViewModel 内部可观察数据
-
数据变化自动驱动 View 刷新,不需要手动调用 View 方法
View <-->[数据绑定]--> ViewModel <--> Model
- ViewModel 不知道 View 是谁;View 订阅 ViewModel 的数据。
技术代表:Android Jetpack ViewModel+DataBinding;Vue、Angular、WPF。
单向绑定 vs 双向绑定
- 单向绑定:ViewModel→View:数据变化更新 UI
- 双向绑定:View↔ViewModel:UI 输入反过来自动回写到 ViewModel
MVVM 优点
- 去掉大量 UI 更新模板代码,不用写
view.setText()这类调用 - ViewModel 不持有 View,规避 MVP 的内存泄漏风险
- ViewModel 独立,易于单元测试,Mock Model 即可
- UI 与业务进一步解耦;页面销毁 ViewModel 可以保留状态(Jetpack ViewModel)
MVVM 缺点
- 双向绑定逻辑藏在框架内部,调试困难,数据流向不直观
- 复杂页面数据状态多,ViewModel 依然容易膨胀
- DataBinding 会增加编译时间;数据变更过多容易引发意外 UI 刷新
- 学习成本高,需要理解响应式、可观察对象
四、三者核心对比表
| 维度 | MVC | MVP | MVVM |
|---|---|---|---|
| 中间人 | Controller | Presenter | ViewModel |
| View 与中间层关系 | View 持有 Controller;Controller 操作 View | Presenter 持有View 接口 | 无引用,靠数据绑定 |
| 更新 UI 方式 | Controller 主动调用 View | Presenter 调用 View 接口方法 | 数据自动驱动 UI |
| View 是否抽象 | 一般不抽象 | 必须抽象为接口 | 不需要接口,绑定字段 |
| 内存泄漏风险 | 中 | 高(Presenter 持有 View) | 低(ViewModel 不持有 View) |
| 模板代码量 | 少 | 多(大量 View 接口) | 中等(框架接管绑定) |
| 单元测试 | 困难 | 优秀(Mock View 接口) | 优秀(Mock 数据) |
| 调试难度 | 简单 | 中等 | 困难(双向绑定黑盒) |
| 适用场景 | 简单页面,快速开发 | 中大型项目,重视单元测试 | 复杂页面,响应式 UI;Vue/WPF/Jetpack |
核心差异通俗总结
- MVC:控制器指挥视图干活;视图和控制器容易粘在一起。
- MVP:Presenter 指挥 View 接口干活;把 UI 行为抽象成接口,方便测试,但是接口写得多。
- MVVM :不再手动指挥 View;数据一变界面自动变,中间人 ViewModel 不认识 View。
误区:MVVM 不是完全消灭业务复杂度,只是转移,ViewModel 依然可能臃肿,需要配合 UseCase、Repository 进一步分层。
五、常见实践建议
- 简单小页面:MVC 够用,不要过度设计
- 需要大量单元测试、不想引入绑定框架:选 MVP
- 复杂 UI、表单多、状态多,使用官方响应式框架(Jetpack、Vue):选 MVVM
- 现实项目不会严格纯净模式:经常出现混合架构,比如 MVVM 里少量手动调用 View。
六、关键陷阱
- MVC 不要把业务全部写 View 层;
- MVP 一定要页面销毁切断 Presenter‑View 引用,防止内存泄漏;
- MVVM 不要把 View 相关逻辑放进 ViewModel,ViewModel 不能持有 Context、View 实例。
如果你需要,我可以给你写一份极简伪代码示例,分别演示 MVC/MVP/MVVM 代码写法对比。
