【架构】MVP 对比 MVVM

核心理念对比

这两种模式都源于同一个目标:将用户界面(UI)逻辑与业务逻辑分离,以提高代码的可测试性、可维护性和可扩展性。它们都是为了解决传统 MVC 模式中,View 和 Model 经常过度耦合的问题。


MVP(Model-View-Presenter)

1. 角色与职责
  • Model(模型):代表数据和业务逻辑。它负责从网络、数据库等获取数据,并处理核心业务规则。与 MVVM 中的 Model 基本一致。
  • View(视图) :负责渲染 UI 元素,并将用户输入(如点击、滑动)委托 给 Presenter 处理。View 层是被动的,它本身不包含任何业务逻辑。
  • Presenter(表示器) :作为 View 和 Model 之间的"中间人"。它从 Model 中获取数据,进行处理,并命令 View 更新界面。它包含了所有的展示逻辑。Presenter 持有 View 的引用
2. 数据流向与交互
  • 用户操作:View 接收到用户操作(如按钮点击),立即将控制权交给 Presenter。
  • 逻辑处理:Presenter 处理用户输入,可能需要向 Model 请求数据或提交数据。
  • 数据返回:Model 将数据返回给 Presenter。
  • 更新界面 :Presenter 接收到数据后,进行格式化、校验等逻辑处理,然后直接调用 View 的方法来更新界面。

关键点 :数据流是单向 的,但 View 和 Presenter 之间的调用关系是双向的。View 调用 Presenter 的方法,Presenter 也调用 View 的方法。它们之间存在紧密的耦合。

3. 优点
  • 高可测试性:由于 Presenter 包含了所有展示逻辑,并且只通过接口与 View 交互,因此可以在没有 UI 的情况下轻松测试 Presenter 的逻辑。
  • 职责清晰:View 只负责显示,Presenter 负责逻辑,分离得很彻底。
4. 缺点
  • 接口膨胀:通常需要为每个 View 定义一个庞大的接口,列出所有可能的 UI 操作方法,这会导致接口中包含很多方法。
  • 紧耦合:Presenter 和 View 是紧密耦合的,一个 Presenter 通常只服务于一个特定的 View,这可能导致在 View 变化时 Presenter 也需要修改。

MVVM(Model-View-ViewModel)

1. 角色与职责
  • Model(模型):与 MVP 中的 Model 完全相同,负责数据和业务逻辑。
  • View(视图) :负责渲染 UI 元素,并绑定 到 ViewModel 的属性上。它通过数据绑定观察者模式来监听 ViewModel 的状态变化,并自动更新。它也会将用户输入直接传递给 ViewModel。
  • ViewModel(视图模型) :它是 View 的抽象 ,代表了 View 的状态和行为。它包含了一系列 View 可以直接绑定的可观察属性 (如 usernameisLoading)和命令 (如 SubmitCommand)。ViewModel 完全不持有 View 的引用,也不知道 View 的存在。
2. 数据流向与交互
  • 数据绑定:View 通过数据绑定机制(如 Android 的 DataBinding、前端的 Vue/React)与 ViewModel 的可观察属性建立连接。
  • 用户操作:用户操作(如输入文字、点击按钮)通过数据绑定或命令直接触发 ViewModel 中相应的方法或属性改变。
  • 逻辑处理 :ViewModel 处理这些输入,与 Model 交互,并更新自己的可观察状态
  • 自动更新 :由于 View 在监听这些可观察状态,当状态改变时,View 会自动被动地更新,而无需 ViewModel 发出任何指令。

关键点 :数据流是双向 的(通过数据绑定),但 View 和 ViewModel 之间的依赖关系是单向的 。ViewModel 对 View 一无所知。这种模式的核心是 "状态驱动""数据驱动" UI。

3. 优点
  • 低耦合:ViewModel 对 View 一无所知,可以在多个 View 之间重用(例如一个 ViewModel 用于手机和平板的不同界面)。
  • 代码简洁 :免去了大量样板代码。你不需要写 textView.setText() 这样的代码,只需要在 XML 或模板中声明绑定关系即可。
  • 数据一致性:由于是"单一数据源",View 的不同部分都绑定到同一个 ViewModel 的属性上,保证了数据状态的一致性。
4. 缺点
  • 调试难度:数据绑定可能会在运行时自动触发,当出现问题时,错误的根源可能不那么明显,调试起来比 MVP 中明确的函数调用更复杂。
  • 学习成本:需要理解数据绑定、观察者模式等概念,对于简单界面可能显得"过度设计"。
  • 内存泄漏风险:如果数据绑定或观察生命周期管理不当,可能会引起内存泄漏。

核心差异总结

特性 MVP MVVM
核心通信方式 双向调用 :Presenter 直接命令 View 更新。 数据绑定/观察 :View 自动观察 ViewModel 的状态变化。
View 的主动性 被动:等待 Presenter 的指令。 被动:响应 ViewModel 的状态变化。
与 View 的耦合 紧耦合:Presenter 持有 View 的引用。 零耦合:ViewModel 对 View 一无所知。
职责中心 Presenter 是指挥者,包含了"如何更新"的逻辑。 ViewModel 是状态容器,包含了"当前状态是什么"的数据。
代码量 需要编写大量 View 接口和手动更新 UI 的代码。 通过声明式绑定,UI 更新代码大大减少。
可测试性 很高,Presenter 逻辑易于单元测试。 很高,ViewModel 同样易于测试,但数据绑定本身测试较复杂。
学习曲线与复杂度 相对简单直观,易于理解和调试。 相对较高,需要掌握数据绑定和响应式编程概念。

如何选择?

  • 选择 MVP

    • 项目相对简单,不需要复杂的数据绑定。
    • 团队对 MVP 更熟悉,或者希望有更清晰的、线性的控制流,便于调试。
    • 在没有良好数据绑定支持的平台或框架上开发。
  • 选择 MVVM

    • 项目复杂,UI 状态繁多,需要保持数据同步。
    • 希望最大限度地减少 View 层的代码,实现"响应式"的UI。
    • 开发平台有成熟的数据绑定库支持(如 WPF, Angular, Android Jetpack, Vue.js)。
    • 追求更高的代码复用性和更低的耦合度。

总而言之,MVP 是一种基于"命令"的模式,而 MVVM 是一种基于"状态"的模式。MVVM 通过数据绑定实现了更彻底的解耦,是现代前端和移动端开发中更受推崇的模式,但 MVP 因其简单性和可控性,依然在许多场景下占有一席之地。

相关推荐
拾忆,想起1 小时前
Dubbo服务调用流程全解析:从请求到响应的微服务通信之旅
服务器·网络·微服务·云原生·架构·dubbo
勿在浮沙筑高台3 小时前
能集成到vs2022里面智能编程工具
架构
S***42803 小时前
后端在微服务中的服务监控
微服务·云原生·架构
阿拉斯攀登4 小时前
Docker 全面解析:从核心概念到实践应用
docker·云原生·容器·架构
张人大 Renda Zhang5 小时前
Java 虚拟线程 Virtual Thread:让“每请求一线程”在高并发时代复活
java·jvm·后端·spring·架构·web·虚拟线程
济南壹软网络科技有限公司5 小时前
架构深潜:通霸IM——私有化部署、全链路开源的高可用企业级即时通讯技术基座
java·架构·开源·即时通讯源码·即时通讯im
Together_CZ5 小时前
FlowFormer: A Transformer Architecture for Optical Flow——一种用于光流估计的Transformer架构
架构·transformer·光流·architecture·光流估计·flowformer·optical flow
社恐的下水道蟑螂6 小时前
深度探索 JavaScript 的 OOP 编程之道:从基础到进阶
前端·javascript·架构
上海云盾第一敬业销售6 小时前
CC防护技术在流量攻击中的架构解析
架构
Embedded-Xin6 小时前
Linux架构优化——spdlog实现压缩及异步写日志
android·linux·服务器·c++·架构·嵌入式