Android中MVC,MVP和MVVM的区别

MVC,MVP和MVVM的区别


看了几个Android介绍MVC模块的博客,我发现他们的描述有些部分都比较不同,于是我自己也来做一个总结。

1. MVC

先说MVC,MVC全称Model View Controller,一种软件设计典范,也就是说这个东西不是Android专有,其他平台软件设计的时候也会用到这个设计方法。
但是不得不说的是,MVC的讲解会比较混乱,很有可能会出现你翻了十个博客,然后MVC的关系图会出现七八种的这种情况。

描述 Android中的对象
Model(模型) 负责提供数据模型以及处理,也负责在数据更改的时候提醒视图。 Model类
View(视图) 数据的可视化,也就是让用户看到数据。 xml文件,自定义View类,自定义Layout类
Controller(控制器) 负责处理用户交互。 Activity,Fragment

Android中MVC,MVP和MVVM的区别
这么说肯定不太好理解,我举一个简单的例子。

前提:app中只有MainActivity一个界面,界面上就一个Textview和Button。

目标:点击button后等待3秒,生成一条随机内容的String,然后删除String中的数字和空格,最后输出到界面上,然后在5秒后,再输出一条新的String删除数字空格后到界面上。

那么在这个例子中,每个层该做什么呢?

  • Model:生成String(提供数据模型);将String进行加工,然后发给View(处理数据模型);5s后再通知一次View(数据更新后提醒)。
  • Controller:点击Button后等待3秒通知Model(处理用户交互)。
  • View:将Button和TextView封装成一个Layout或者View;显示TextView的内容(数据可视化)。
    Android中MVC,MVP和MVVM的区别
    其中MainLayout将Textview和Button封装在一起。

Button的按钮监听会不统一的可能写在View(自定义View)也可能写在Controller(Activity)中。

也有一种说法是Controller负责数据的加工处理,这种情况下String的删除数字和空格会交由Activity来做,且Controller层和Model层会变成两个相互的箭头。这个内容我会在MVP里说。

这么一举例,就可以明显的发现MVC的优点了:

  1. 逻辑分离,专事专办,视图层和业务层分离,耦合性低(一边只负责显示String,一边只负责生成和加工String)。
  2. 可维护性高(这个也是因为上一点,分离了就更好维护了)。
  3. 代码的重用性高(如果哪天别的控件需要这个String了,就可以直接调用,如果不分离的话,整段代码就要再抄一遍)。

与此同时,MVC的一些缺点就显示出来了:

  1. 中小型项目用起来太麻烦(不就一个监听事件输出String的方法吗,我一个函数就搞定了还搞这么多类?)。
  2. VC层耦合性过高,这个是特定针对Android的,因为在Android端,C层代表的是Activity/Fragment,这个是我们主要的用户交互界面,它总是会不可避免的染上一堆视图的逻辑(比如Activity/Fragment切换,显示Dialog,绑定控件)。这种情况下C层并没有完全的C,而加入了一部分V层的操作。
  3. M层的逻辑太多,M层不仅要负责数据的生成,还要负责数据的加工,更要负责视图的提醒这种情况下M层的任务太重且类型太多,就不易于维护。

2. MVP

MVP是基于MVC而生成的,所以明白了MVC,就可以容易理解MVP模式。
MVP全称Model View Presenter,当然也是设计典范。

描述 Android中的对象
Model(模型) 负责提供数据模型。 Model类
View(视图) 数据的可视化。 主要是Activity,Fragment
Presenter/Controller(都叫Presenter了,找不到中文) 负责处理用户交互和数据加工。 Presenter类/Controller类

Android中MVC,MVP和MVVM的区别
之前MVC的关系图看的确实是有些混乱,一些指向又是实线又是虚线的,然后还弄了个三角关系。但是在MVP中,P层是完全隔断了V层和M层的联系,成为了一个中间地带。

对比一下MVC层,再看看MVP层中做了哪些不同的事吧,用一个具体的例子来举例(其实就是MVC的例子,防止翻回去看,在下面复制了一遍)。

前提:app中只有MainActivity一个界面,界面上就一个Textview和Button。

目标:点击button后等待3秒,生成一条随机内容的String,然后删除String中的数字和空格,最后输出到界面上,然后在5秒后,再输出一条新的String删除数字空格后到界面上。

那么在这个例子中,每个层该做什么呢?

  • Model:生成String后发给Presenter(提供数据模型)。
  • View:显示TextView的内容(数据可视化);点击Button后报告给Presenter(也就是Button的监听)。
  • Presenter/Controller:收到等待3秒通知Model,再等待5秒后再通知Model(处理用户交互);String的删除数字和空格(数据加工);加工后的数据发给View。
    Android中MVC,MVP和MVVM的区别

你会发现,我上面MVC所说的Controller层负责数据的加工,其实和MVP的内容很相像,其实就差不多是MVP那意思了。

那么对比MVC,MVP做了哪些改进:

  1. View层终于从高耦合中解放了,Activity这次只负责视图的处理部分,所有的视图都归他管,他不用再去处理业务逻辑了。
  2. Model也从多种类型的复杂任务中解放了,这次它只负责提供数据模型(在项目中一般是数据库或者网络),如果哪天需求变成了删除String中的字符,Model层也完全不用动,因为那个任务现在归Presenter管。
  3. View层和Model层完全分离,会出现有时候只要改动Model层而完全不用修改View层的情况,反过来也有,维护起来就更方便了。

但是MVP模式也依旧有一些缺点:

  1. 中小型项目不适用,这个是继承自MVC模式的缺点了。
  2. Presenter和View层的耦合度有点高,一般来说如果要改动View层那么很有可能Presenter层也要跟着改动。

3. MVVM

接下来就可以说MVVM的模式了,这个MVVM有说是从MVC来的,也有说是MVP来的,我这里就当做是MVP来的。
MVVM全称Model View ViewModel,这里请不要误会,虽然是MVVM,但是实际上也是三层,第三层就是VM层。

描述 Android中的对象
Model(模型) 负责提供数据模型。 Model类
View(视图) 数据的可视化。 主要是Activity,Fragment
ViewModel 负责处理用户交互和数据加工。 ViewModel类

Android中MVC,MVP和MVVM的区别
一看之下MVVM看上去和MVP的区别不大,现在来介绍一下两者的区别。
在MVVM中,VM层取代了原先的P层,然后两者之前的两个箭头变成了一个双向箭头,这就是MVVM相对于MVP的变化。
VM层和V层在MVVM中实现了一个双向的数据绑定,在他们中间还隐藏了一个绑定器Binder。
Android中MVC,MVP和MVVM的区别
我之前看了很多MVVM介绍的博客,他们都说到了数据绑定这个词,那么什么是数据绑定?我再举之前那个例子。

前提:app中只有MainActivity一个界面,界面上就一个Textview和Button。

目标:点击button后等待3秒,生成一条随机内容的String,然后删除String中的数字和空格,最后输出到界面上,然后在5秒后,再输出一条新的String删除数字空格后到界面上。

在之前MVP模式中,V层的任务是绑定控件和显示String的内容到TextView上。也就是说,无论如何一定会调用到textview.setText(string);这个方法对吧,但是在MVVM模式中,你可以不用再调用setText了。MVVM中只要string这个变量一更新,Textview就会自动显示更新后的值,这就是数据绑定。

了解了数据绑定后,再来看看MVVM中每个层的具体任务:

  • Model:生成String后发给Presenter(提供数据模型)。
  • View:实现绑定器,实现Button监听。
  • ViewModel:收到等待3秒通知Model,再等待5秒后再通知Model(处理用户交互);String的删除数字和空格(数据加工后会自动更新)。
    Android中MVC,MVP和MVVM的区别
    在MVVM中,View层只需要实现绑定器和监听即可,实际上的视图内容显示都由绑定器来完成(而这个绑定器对于我们而言只要设置好就行),View层的任务因此而抽象化了非常多。

那么,说了这么久绑定器绑定器的,这个绑定器又到底是个啥?
别的语言我不太清楚,但是在Android中,google公司特地的推出了一个DataBinding框架,这个东西就是我们实现绑定器的具体工具了。所以经常会看到Android MVVM的介绍博客说着说着就变成DataBinding的介绍,要注意两者是完全不同的东西,一个是设计典范,一个是工具!

关于DataBinding怎么使用,参考这篇:
Android DataBinding 从入门到进阶 - 简书
https://www.jianshu.com/p/bd9016418af2

最后再总结一下MVVM相对MVP的改进:

  1. 数据绑定让V层抽象化,代码进一步的减少,更加方便了。
  2. 相对于MVP,VM层可以一次性对应多个V层了,在MVP模式中,经常是一个页面一个Presenter,但是在MVVM中,会出现多个页面但是只有一个ViewModel的情况,这个是真的是提高了很多代码重用性。

以及MVVM的缺点:

  1. 调试变得更加困难,以前如果在V层报错的话,你会明显的看到V层的报错信息,但是在MVVM中由于是绑定器负责更新,报错后的调试就更加困难了(不好定位出错的地方,VM层报错的时候,可能是VM层出错,也可能是M层出错,你的String出错了,不知道是生成的时候出错,还是修改的时候出错)。
  2. 数据双向绑定不利于代码重用,但是这一点我存疑,因为在Android中DataBinding是可以实现单向绑定的。不过View层确实是不好代码重用了。
  3. 一个大的模块中,model也会很大,虽然使用方便了也很容易保证了数据的一致性,当长期持有,不释放内存,就造成了花费更多的内存(这个我真不懂,是我复制来的)。

参考材料

MVC 模式 | 菜鸟教程
https://www.runoob.com/design-pattern/mvc-pattern.html
MVC框架_百度百科
https://baike.baidu.com/item/MVC%E6%A1%86%E6%9E%B6/9241230?fromtitle=mvc&fromid=85990&fr=aladdin
Android App的设计架构:MVC,MVP,MVVM与架构经验谈-android,mvp,mvc 相关文章-天码营
https://www.tianmaying.com/tutorial/AndroidMVC
https://blog.csdn.net/huangliniqng/article/details/85804875