【Android】MVC,MVP,MVVM的优缺点
👨🎓作者简介:一位喜欢写作,计科专业大二菜鸟
🏡个人主页:starry陆离
🕒首发日期:2022年5月22日星期日
🌌上期文章:【Android开源控件】drawerlayout侧滑菜单(抽屉效果)
📚订阅专栏:Android基础入门如果文章有帮到你的话记得点赞👍+收藏💗支持一下哦
@TOC
MVC(最经典)
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构.
优点
- 耦合性低
视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。
- 重用性高
MVC模式允许使用各种不同样式的视图来访问同一个服务器端的代码,因为多个视图能共享一个模型
- 部署快,生命周期成本低
MVC使开发和维护用户接口的技术含量降低。使用MVC模式使开发时间得到相当大的缩减,它使程序员(Java开发人员)集中精力于业务逻辑,界面程序员(HTML和JSP开发人员)集中精力于表现形式上。
- 可维护性高
分离视图层和业务逻辑层也使得WEB应用更易于维护和修改。
缺点
- 完全理解MVC比较复杂。
- 调试困难。
- 不适合小型,中等规模的应用程序
- 增加系统结构和实现的复杂性
- 视图与控制器间的过于紧密的连接并且降低了视图对模型数据的访问
视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
MVP(最常用)
MVP的全称为Model-View-Presenter,Model提供数据,View负责显示,Controller/Presenter负责逻辑的处理。MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter(MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过Controller。表示器包含大多数表示逻辑,用以处理视图,与模型交互以获取或更新数据等
也就是我们通常意义上的表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)
优点
- View与Model完全隔离。
得益于此,Model和View之间具有良好的松耦合设计,这意味着,如果Model或View中的一方发生变化,只要交互接口不变,另一方就没必要对上述变化做出改变。这使得Model层的业务逻辑具有很好的灵活性和可重用性。
- Presenter与View的具体实现技术无关。
也就是说,采用诸如Windows表单,WPF,Web表单等用户界面构建技术中的任意一种来实现View层,都无需改变系统的其他部分。甚至为了使B/S,C/S部署架构能够被同时支持,应用程序可以用同一个Model层适配多种技术构建的View层。
- 可以进行View的模拟测试。
过去,由于View和Model之间的紧耦合,在Model和View同时开发完成之前对其中一方进行测试是不可能的。出于同样的原因,对View或Model进行单元测试很困难。现在,MVP模式解决了所有的问题。在MVP模式中,View和Model之间没有直接依赖,开发者能够借助模拟对象注入测试两者中的任一方。
MVP&MVC
MVP是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter(MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过Controller。
缺点
- MVP的明显缺点是增加了代码的复杂度,特别是针对小型Android应用的开发,会使程序冗余。
- Presenter中除了应用逻辑以外,还有大量的View->Model,Model->View的手动同步逻辑,会导致Presenter臃肿,维护困难。
- 视图的渲染过程也会放在Presenter中,造成视图与Presenter交互过于频繁,如果某特定视图的渲染很多,就会造成Presenter与该视图联系过于紧密,一旦该视图需要变更,那么Presenter也需要变更了,不能如预期的那样降低耦合度和增加复用性。
虽然MVP 的表示层Presenter阻断了展现层view和模块层model的直接联系,但是展示层中的每个控件都得声明,对每个控件都需要使用 get方法获取控件的值,使用 set 方法更新控件的值。对展示层中复杂的逻辑操作会使的Activity变得越来越臃肿
MVVM(最新)
MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版
View:主要进行视图控件的一些初始设置,不应该有任何的数据逻辑操作。
Model:定义实体类,以及获取业务数据模型,比如通过数据库或者网络来操作数据等。
ViewModel:作为连接 View 与 Model 的中间桥梁,ViewModel 与 Model 直接交互,处理完业务逻辑后,通过 DataBinding 将数据变化反应到用户界面上。
MVVM 与 MVP 的最明显区别是 MVVM 模式中需要用到DataBinding,DataBinding 是指数据绑定,DataBinding 是在布局文件中实现数据绑定声明,数据的变化会引起视图的自动更新,使用 DataBinding 会减少逻辑代码。ViewModel 可以理解成是 View 中的数据模型和Presenter 的合体,它通过双向绑定解决了 MVP 中 Presenter与 View 联系紧密的问题
优点
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点
- 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
- 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
- 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计
- 可测试。界面素来是比较难于测试的,测试可以针对ViewModel来写。
缺点
- 数据绑定使得 Bug 很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。
- 一个大的模块中,model也会很大,虽然使用方便了也很容易保证了数据的一致性,当长期持有,不释放内存,就造成了花费更多的内存。
- 数据双向绑定不利于代码重用。客户端开发最常用的重用是View,但是数据双向绑定技术,让你在一个View都绑定了一个model,不同模块的model都不同。那就不能简单重用View了。
参考资料
[1]崔慧娟.MVVM模式在Android项目中的应用[J].信息与电脑(理论版),2021,33(06):1-3.
[2]曾露.MVP模式在Android中的应用研究[J].软件,2016,37(06):75-78.
下期预告
Android中是如何实现视图与数据的双向绑定的?
我的理解就是:我们常说的业务逻辑层,数据传输层,表现层
存在的问题:
Activity太重了,
推出
vue->标准的mvvm框架:
数据绑定
在gradle中打开dataBinding,与打开viewBinding类似
dataBinding{
enabled=true;
}
改造布局文件。按住alt+enter获取提示,选中第一个(如果没有提示检查是否联网,打开dataBinding是否成功)
之后可以看到布局文件已经被修改了
在<data></data>
标签中定义数据,在<androidx.constraintlayout.widget.ConstraintLayout>
中定义布局并且绑定数据,这类似于前端vue框架中的数据视图双向绑定
事件绑定
dataBinding除了可以绑定数据之外,它还可以帮我们绑定事件
定义一个内部类
/*定义一个内部类*/
publicclassMyclick{
publicvoidonClick(Viewview){
Log.i("myclick", "onClick: "+"事件绑定成功");
}
}
同样的需要在xml文件的data标签中定义这个点击事件
在xml文件中设置一个按钮,并为其绑定点击事件
使用onClick属性(在vue中的数据绑定也是这样的方式哦)
android:onClick="@{myclick.onClick}"
通过事件过滤可以发现事件绑定已经成功
为实体类继承一个类
点击按钮会刷新数据
基本类型的值也不会刷新
不再使用String name;
使用ObservableField
泛型封装String
使用内置的set添加数据
添加修改数据也是使用set
输入控件改变值---》数据的双向绑定
android:text="@={name}"
加载网络图片
课堂案例
https://starry-lixu.oss-cn-hangzhou.aliyuncs.com/img/20220124211431.png
https://starry-lixu.oss-cn-hangzhou.aliyuncs.com/img/20220521232757.png
https://starry-lixu.oss-cn-hangzhou.aliyuncs.com/img/20220124211431.png