首先辨析一下架构模式和设计模式的关系:
MVP、MVC、MVVM是三种常见的前端架构模式,通过分离关注点来改进代码组织方式。而设计模式只是为了解决一类问题而总结出的抽象方法。一种架构模式往往能使用多种设计模式,如工厂模式、抽象模式、单例模式。本文整合了网上一些博客的观点,仅作学习记录,参考博文已附链接。
MVC和MVP
https://cloud.tencent.com/developer/article/1383090
https://blog.csdn.net/qq_31852701/article/details/52946127
MVVM和ViewModel
在介绍这三种架构及个人理解之前声明一点,任何架构都没有绝对的划分,这只是一种思想和良好的代码习惯,我的理解也不深入,欢迎大家批评指正~
MVC
Model模型层,和数据获取、处理相关的层,负责存储系统的中心数据。M最接近获取数据的API或数据库。对数据库的操作、以及其他和数据有关的的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。
View视图UI层,负责将信息显示给用户,可以定义多个View,通过Controller的调用,对Model进行不同的展示。
Controller控制层,负责处理用户和应用的交互,从视图读取数据,通过监听事件响应用户对View的操作,再调用Model对数据进行更新,完成model与view的同步。
MVC重要特点就是两种分离:
视图和数据模型的分离:使用不同的视图对相同的数据进行展示;分离可视和不可视的组件,能够对模型进行独立测试。因为分离了可视组件减少了外部依赖利于测试。(数据库也是一种外部组件)
视图和表现逻辑(Controller)的分离:Controller是一个表现逻辑的组件,并非一个业务逻辑组件。MVC可以作为表现模式也可以作为建构模式,意味这Controller也可以是业务逻辑。分离逻辑和具体展示,能够对逻辑进行独立测试。
大家可以这样来理解:模型是我们想要操作的对象,但它没有用户界面。视图表示它在屏幕上的显示,代表流向用户的数据。控制器定义用户界面对用户请求的响应方式,负责把用户的动作转成针对Model的操作。Model 通过更新View的数据来反映数据的变化。
我看过网上很多博主画的流程图有失偏颇,甚至把MVC和MVP相混淆,所以我放一张书上的图,相对更权威吧。
我大致讲一下我对这张图的理解,当然,我的理解也不完全正确,欢迎大家向我提出质疑。
View—>Model 视图是解释模型的载体,可以直接查询已适配的模型得到数据(可能适配用词不当)
View—>Controllerl—>View 视图将用户输入发给控制器,控制器根据用户请求选择响应的视图,并将对应的模型传给该视图。
View—>Controllerl—>Model—>View用户有模型更新的请求,导致模型状态发生改变,而模型将状态的改变反馈给所适配的视图。
这么来看,Model、View、Controller三者之间是相互可见的,而Controller到底是表现逻辑的组件还是业务逻辑的组件,并不清晰。模块之间界限不明显,Model和View中也存在少量逻辑代码,耦合度低。再者,虽然Model和View之间有关联,但数据的改变和更新却必须经过Controller,由开发者手动实现,若数据更新的地方比较多,维护数据状态的代码也会复杂起来。带着这两个不足之处,我们来看看MVP和MVVM解决了什么问题吧。
MVVM
MVVM 是Model-View-ViewModel 的缩写,MVVM与MVC最大的区别就是:它实现了View和Model的自动同步,也就是当Model的属性改变时,该属性对应View层显示会自动改变。在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。开发者只需关注业务逻辑,不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
比如说,我们可以通过一个String
类型的状态来表示一个TextView
,同理,我们也可以通过一个List<T>
类型的状态来维护一个RecyclerView
的列表——在实际开发中我们通过观察这些数据的状态,来维护UI的自动更新,这就是 数据驱动视图(观察者模式):每当String
的数据状态发生变更,View层就能检测并自动执行UI的更新,同理,每当列表的数据源List<T>
发生变更,RecyclerView
也会自动刷新列表。
MVVM的优点显而易见的是:双向绑定技术,当Model变化时,ViewModel会自动更新,View也会自动变化,能很好的做到数据一致性。View的功能有了进一步的加强,UI和业务逻辑解耦。但与此同时,数据绑定使得 Bug 不易调试,也会使得一个位置的 Bug 被快速传递到别的位置。Google有出ViewModel等组件试图规范MVVM在安卓开发中的书写,初学者用起来上手快,但出于想学习架构思想的目的,我认为还是MVC和MVP更合适。
MVP
MVP对逻辑进行了严格的提取,Presenter用于连接Model和View,负责所有逻辑处理(不仅限于表现逻辑,而是具体的业务逻辑)。
在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。Presenter就像View和Model的发言人(契合Presenter的字面义),它们相互之间是不可见的,只能通过Presenter来“传话”。View向Presenter请求数据,Presenter把数据送到Model,或者Presenter监听Model的数据变化,接收View层的动作,通知View层的视图发生变化。
Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现,其中的View是很薄的一层,只应该有简单的Set/Get的方法,用户输入和设置界面显示的内容,除此就不应该有更多的内容,绝不容许View直接访问Model。而且,Presenter与具体的View是没有直接关联的,而是通过接口进行交互,从而使得在变更View时候可以保持Presenter的不变,可以多次复用。
由此看出,MVP代码解耦性应该是最好的、而且代码结构清晰、可复用性高、扩展性高,方便单元测试。
选型分析
因项目最终选型是MVP,下面主要比较一下MVVM和MVP、MVC和MVP,给出我选型的理由。
MVVM和MVP比较
MVVM的双向绑定技术和数据状态管理是它的技术亮点,但这是把双刃剑,带来的问题如下:View和ViewModel之间界限不清,对初学者而言写出结构清晰的代码较难;绑定带来的就是View不够灵活,复用性不高;而且绑定使得bug不易调试。我们项目对View和Model数据更新的需求不高,而且希望能写出结构规范、清晰的代码,所以我们不选择MVVM。
MVC和MVP比较
Android开发天然的就是MVC结构,Activity对应了MVC中的V和C,随着项目的深入,Activity处理的东西越来越多,代码也越来越臃肿,而且在修改需求时,因为V和C的耦合性,即使是一个小小的View的改变,也要在Activity臃肿的代码中找上半天,这对于程序员而言是件非常痛苦的事。
为了解决这种不必要的痛苦,提高开发效率,MVP把逻辑层抽出来成P层,Activity只充当V的角色,业务逻辑控制交给了Presenter。要是遇到需求逻辑上的更改就可以只需要修改P层了或者遇到逻辑上的大改我们可以直接重写一个P也可以,所以MVP模式对于APP来对控制逻辑和UI的解耦来说是一个不错的选择,所以我们最终选择的是MVP架构模式。
上面贴的两个链接对两种模式的比较写得非常清楚了,博主开发经验丰富,也给出了MVP的demo,建议大家去学习一下。希望大家能有所收获~~~