MVC、MVP、MVVM架构理解

一、MVC

概念:Model ,View,Controller

视图(View):管理作为位图展示到屏幕上的图形和文字输出;
控制器(Controller):接收用户的输入并依照用户的输入操作模型和视图;
模型(Model):管理应用的行为和数据,响应数据请求(来自视图)和更新状态的指令(来自控制器);

1、传统的MVC架构图
image.png

可以看出在 MVC 中的依赖关系,只有模型层可以单独工作,而视图层和控制器层都依赖与模型层中的数据。会导致复用困难,不好测试,代码也不够优雅。

2、主动通知型MVC(改进版)
image.png

“发布 - 订阅” 模式来提供了一种机制来提醒其他对象的状态变化,避免引入依赖关系。各个View实现Observer接口并向Model注册。当Model发生变化时,Model会遍历所有注册的观察者并通知他们相关的变化。

3、iOS版本MVC
image.png

苹果认为传统的MVC模式中,View通过Observer模式直接观察Model对象以获取相关的通知,而这样的设计会导致View和Model对象不能被广泛复用,因为View与其观察的Model之间存在耦合关系。因此,苹果版MVC与传统MVC的区别是,隔离了View和Model。
实际上 iOS的MVC模式有点像MVP的架构了。

二、MVP

1、MVP概念

MVP可以认为是MVC演化而来的变种,MVP(Modell-View-Presenter)模式就是为了解决MVC中Controller越来越臃肿的问题,进一步明确代码分工。MVP与苹果版MVC非常相似,但是它们的从属关系有所不同(实线表示持有)。

如下图所示
MVP模式中View持有Presenter,Presenter持有Model,View不能直接访问Model;
而MVC模式中Controller持有View和Model。


image.png

MVP 实现将UI逻辑和数据逻辑隔离,而隔离之后就可以方便地对数据逻辑部分进行单元测试。

2、MVP 本质

面向接口的编程方式,即依赖倒置的设计原则,提供一个Presenter类作为中间环节,达到复用某些能力给各个不同的页面。一般来说,会设计不同IPresenter接口出来,让不同的页面进行依赖调用,这样可实现更好的业务功能复用性。即让页面依赖抽象,而不依赖具体实现。这是一个比较广义的架构模式,有着非常广泛的应用,在大型软件系统设计,开源框架的设计中都非常常见。在很多开源库设计中,还会用到控制反转、依赖注入的模式,暴露更灵活调用方式,由外部调用者创建具体的实现对象传入到框架,而非框架写死。

3、和MVC的对比

MVP优点:
1.降低耦合度、模块职责划分明显:View不直接与Model交互,而是通过与Presenter交互来与Model间接交互
2.方便测试:Presenter与View的交互是通过接口来进行的,更有利于添加单元测试
3.部分可复用:通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑,业务相似的时候也可以多同个View共享一个Presenter。

MVP缺点:
额外的代码复杂度、接口类非常多

三、MVVM

1、MVVM概念
image.png

image.png

从 Model-View-ViewModel 这个名字来看,它由三个部分组成,也就是 Model、View 和 ViewModel
Model 定义用户界面所需要被显示的数据模型,一个模型包含着相关的业务逻辑(在实际开发中,数据相关的业务逻辑都会放到服务器)。
View 视图为呈现用户界面的终端,用以表现来自 Model 的数据,和用户命令路由再经过 Presenter 对事件处理后的资料。
ViewModel 在原有Presenter层的基础上,将业务逻辑封和组件进行双向绑定(data-binding),达到同步更新的目的。

2、优缺点

优点

  • 含有MVP的优点,降低了View和Model之间的耦合;分离了业务逻辑和视图逻辑
  • 增加了双向绑定(data-binding)等操作,使数据推送/更新等操作更自动化。
    缺点
  • ViewModel层的膨胀的问题依然没有得到解决,只能拆分为多个子ViewModel。
3、基于Android MVVM(JetPack)的一些理解

MVVM 相比MVP 是一个比较狭义的架构模式,比较适用于页面开发,由于页面重建、UI状态管理、事件分发存在很多安全隐患,所以做了一些约束条件,使得页面间通信、事件分发、生命周期回调更加安全和一致,本质上是一种数据驱动的思想。

在Android这种页面开发居多的软件系统中,Google提供了一套MVVM架构的组件框架,包括LifeCycle、LiveData、ViewModel、Databinding等。LifeCycle是通过将生命周期接口下层到SDK中,实现生命周期事件分发的一致和安全,在SDK中定义规范了一套生命周期的状态机,严格管理各个生命周期状态的使用范围,并且在页面销毁的时候注销了接口来确保没有内存泄露的发生。

LiveData是通过将读写分离,严格控制写的范围来保证事件分发的一致性,只在一处进行写事件,LiveData有一个粘性问题需注意,可能在页面返回的时候通知一遍最新数据(数据倒灌)导致一些非预期的展示。

在私域中(例如 Fragment 私有的 ViewModel 中),我们可以直接使用 MutableLiveData,每当需要通知 DataBinding 绑定的控件刷新数据时,我们在 Fragment 中直接 setValue

而对于跨域的通信,我们则不能拿到公域的 MutableLiveData 和 setValue,而是通过 SharedViewModel 的各种 request 方法去向这位领导请示,SharedViewModel就作为统一决策者,SharedViewModel中的livedata对象是可以调用setValue的,但暴露出去的这个livedata是一个包装的父类ProtectLiveData(setValue方法是protect的,让外部无法直接调用发送消息),只能由SharedViewModel自己内部决策并最终通过 LiveData(Protect父类)来通知到所有观察者页面。


image.png

LiveData 框架的存在就是为了支持这类事,也即 LiveData 的本质就是提供 “生命周期安全的、可靠一致的” 消息分发体验。

ViewModel都会配合LiveData来使用,ShareViewModel一般用于页面间通信,发送更全局的事件,生命周期更长,而StateViewModel一般管理页面内的状态,分担Activity和Fragment的压力,设置不同作用域的ViewModel,比如可以分开拿Activity和Fragment的ViewModel对象,作用域范围是不同,也可以更好的避免内存泄露。

这套框架的核心目标是增加约束条件,使得Android在UI页面开发上更加一致和规范化,让页面通信、事件分发、页面重建、状态管理、生命周期管理能够更一致和更安全。

image.png

你可能感兴趣的:(MVC、MVP、MVVM架构理解)