对MVC,MVP和MVVM的理解

Posted 蟹老板工作室

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对MVC,MVP和MVVM的理解相关的知识,希望对你有一定的参考价值。

MVC

理想的MVC

MVC的理想模型如下图所示:

各层的职责如下所示:

Models: 数据层,负责数据的请求和存储以及处理
View: 展示层,负责View和动画效果的展示,以及用户的交互
Controller: 控制器层,负则连接View和Model,对view的交互事件有controller层处理传递给model,model处理再交互传递给Controller,Controller传递给view

M和View应该是完全隔离的,由C作为中间人来负责二者的交互,同时三者是完全独立分开的,这样可以保证M和V的可测试性和复用性,但是一般由于C都是为特别的应用场景下的M和V做中介者,所以很难复用。

MVC在ios里面的应用

实际开发里iOS里面的MVCD额实现方式很难做到理想的那样,由于Apple的规范,一个界面的呈现需要构建一个ViewController,而每个VIewController都带有view,这样就到C和V紧密耦合在一起构成了IOS里面的C层,明显不符合MVC的初衷
Apple里的MVC真正写出来大概如图所示:

对于简单的界面来说,ViewController确实可以提高开发效率,但是一旦需要构建复杂的界面,那么ViewController就会变得特别臃肿。

iOS的MVC职责

Controller(VC):

  1. 生成View,组装View

  2. 响应View的事件,或者作为View的代理

  3. 调用Model的数据获取接口,拿回返回的数据处理加工渲染到View的展示

  4. 处理View的生命周期(init->willMoveToSuperView->didMoveToSuperView->didAddSubView->layoutSubViews->drawRect->willMoveToSuperView->didMoveToSuperView->removeFromSuperView->dealloc->willReMoveSuperView)

  5. 处理View的跳转

VC职责简化

  1. 生成的View添加到self.view上面,逻辑不在ViewController里

  2. 管理View的声明周期

  3. 每个子view设置代理,代理又Controller实现。

Model :

  1. 业务逻辑封装

  2. 提供数据接口给Controller使用

  3. 数据持久化存储与读取

  4. 作为数据模型存储数据

    Model层不仅仅是实体类,他还包含了业务逻辑处理以及数据存储等其他操作。

View层:

  1. 界面元素搭建,动画展示

  2. 接受用户操作并提供反馈

MVC优缺点

优点

  1. 增强代码复用性耦合性低: V对外只暴露Set方法,对M甚至C都是个例状态,复用没问题

  2. 解决代码臃肿: 布局转移到了View层,业务逻辑转移到了Model层

  3. 易拓展:无论产品想增加或者模块,只需增加响应的MVC模块

  4. 可维护:各个模块相互隔离,哪里出错改哪里,不影响其他模块。

缺点

  1. 简单的小型项目,使用MVC设计反而会降低开发效率层和层虽然相互分离,但是之间关联性太强,没有做到独立的重用。

  2. 对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率

  3. 视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。

  4. 依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。

MVP

由来

MVC的缺点在于并没有区分View和Model层,  MVP针对以上缺点做了优化, 它将业务逻辑和业务展示也做了一层隔离, 对应的就变成了MVCP.
M和V功能不变, 原来的C现在只负责布局, 而所有的业务逻辑全都转移到了P层。P层处理完了业务逻辑,如果要更改view的显示,那么可以通过回调来实现,这样可以减轻耦合,同时可以单独测试P层的业务逻辑,
MVP从视图层中分离了行为(事件响应)和状态(属性,用于数据展示),它创建了一个视图的抽象,也就是presenter层,而视图就是P层的『渲染』结果。P层中包含所有的视图渲染需要的动态信息,包括视图的内容(text、color)、组件是否启用(enable),除此之外还会将一些方法暴露给视图用于某些事件的响应。

MVP结构


Presenter处理View的业务逻辑,与View耦合,Persenter也给视图暴露接口与其通信,他将原来需要在Controller层里面处理的逻辑移到了Persenter层

MVP的职责

VC层:

  1. 生成的View添加到self.view上面

  2. 管理View的声明周期

  3. 通过P层去获取数据然后渲染到View上面展示。

Controller层:

  1. 生成view,实现view的代理和数据源

  2. 绑定view和presenter

  3. 调用presenter执行业务逻辑

  4. 负责界面跳转

View层:

  1. 监听P层数据更新通知,刷新页面展示

  2. 点击事件触发时调用P层响应的方法

  3. 界面元素搭建,动画展示

  4. 接受用户操作并提供反馈

Model层:

  1. 与MVC的model层一样


Persneter层:

  1. 实现view的事件处理逻辑,暴露相应的接口给view的事件调用

  2. 调用model的接口获取数据,然后加工数据,封装成view可以直接用来显示的数据和状态


这里又有两种不同的实现方式:

让P持有V,P通过V的暴露接口改变V的显示数据和状态,P通过V的事件回调来执行自身的业务逻辑
让V持有P,V通过P的代理回调来改变自身的显示数据和状态,V直接调用P的接口来执行事件响应对应的业务逻辑
第一种方式保持了view的纯粹,只是作为被动view来展示数据和更改状态,但是却导致了P耦合了V,这样业务逻辑和业务展示有糅合到了一起,和上面的MVC一样了。
第二种方式保证了P的纯粹,让P只做业务逻辑,至于业务逻辑引发的数据显示的变化,让view实现对应的代理事件来实现即可。这增加了view的复杂和view对于P的耦合。

MVP相对于MVC, 它其实只做了一件事情, 即分割业务展示和业务逻辑. 展示和逻辑分开后, 只要我们能保证V在收到P的数据更新通知后能正常刷新页面, 那么整个业务就没有问题. 因为V收到的通知其实都是来自于P层的数据获取/更新操作, 所以我们只要保证P层的这些操作都是正常的就可以了. 即我们只用测试P层的逻辑, 不必关心V层的情况

MVVM

MVVM其实是在MVP的基础上发展起来的。那么MVVM在MVP的基础上改良了啥呢?答案就是数据绑定。从 Model-View-ViewModel 这个名字来看,它由三个部分组成,也就是 Model、View 和 ViewModel;其中视图模型(ViewModel)其实就是 MVP 模式中的P,在 MVVM 中叫做VM。


除了我们非常熟悉的 Model、View 和 ViewModel 这三个部分,在 MVVM 的实现中,还引入了隐式的一个 Binder层,这也是MVVM相对MVP的进步,而声明式的数据和命令的绑定在 MVVM 模式中就是通过binder层来完成的,RAC是iOS下binder的优雅实现,当然MVVM没有RAC也完全可以运行。
下图展示了iOS下的MVC是如何拆分成MVVM的:

MVVM和MVP相对于MVC最大的改进在于:P或者VM创建了一个视图的抽象,将视图中的状态和行为抽离出来形成一个新的抽象。这可以把业务逻辑(P/VM)和业务展示(V)分离开单独测试,并且达到复用的目的,逻辑结构更加清晰

MVVM层职责

MVVM隔层职责和MVP类似,VM对应P层

MVVM相对于MVP的改进

MVVM相对于MVC的改进是对VM/P和view做了双向的数据和命令绑定
MVP的view触发P的业务逻辑,然后P再回调改变View的显示的操作,使用MVVM的数据绑定来实现让逻辑更加清晰,代码也更少。这就是MVVM相对于MVP的改进之处

缺点

View和Viewmodel因为双向绑定所以没有复用性。

以上是关于对MVC,MVP和MVVM的理解的主要内容,如果未能解决你的问题,请参考以下文章

Android 中的MVC MVP MVVM

你真的理解了MVC, MVP, MVVM吗?

Vue实战3.基础知识_MVC/MVP/MVVM

关于vue项目中mvvm模式的理解

mvc mvp mvvm的区别

这些图中箭头的图例是啥(MVC - MVP - MVVM)?