设计模式MVC、MVP、MVVM

MVC、MVP和MVVM是什么?

  • MVC:Model-View-Controller,是一种分层解偶的框架,Model层提供本地数据和网络请求,View层处理视图,Controller处理逻辑,存在问题是Controller层和View层的划分不明显,Model层和View层的存在耦合。
  • MVP:Model-View-Presenter,是对MVC的升级,Model层和View层与MVC的意思一致,但Model层和View层不再存在耦合,而是通过Presenter层这个桥梁进行交流。
  • MVVM:Model-View-ViewModel,不同于上面的两个框架,ViewModel持有数据状态,当数据状态改变的时候,会自动通知View层进行更新。

MVC

1.什么是MVC?

1). 软件工程中的一种软件架构, 全称为"Mode–View–Controller", 即为"模型–视图–控制器"

2). MVC将交互式的应用程序分为3个组件:

  • Mode(模型) : 模型层, 包括实体模型与业务模型, 主要作用是完成业务逻辑处理和数据封装。在Android中, 对应实体类/业务类/DAO类
  • View(视图) : 显示层(表示层), 向用户显示信息。在Android中, 对应布局和自定义控件类
  • Controller(控制器) : 控制层, 处理用户输入, 并实现View层与Mode层的协同处理。Android中, 对应Activity

缺点:存在问题是Controller层和View层的划分不明显,Model层和View层的存在耦合。

2.理解MVC

1.基本结构图
设计模式MVC、MVP、MVVM_第1张图片
2.Android中的MVC结构:

  • M模型层:
    com.mvc.bean: 实体类包
    com.mvc.utils: 工具包(简单的业务逻辑处理)
    com.mvc.dao: 数据库操作
    com.mvc.net: 网络请求

  • V视图层:
    res下的layout, drawable, values等
    自定义View类等

  • C控制层:
    Activity
    其它应用组件等

3.使用MVC模式的好处 /如果不用MVC会有什么问题?

1). 如果不用View层(布局)?
问题: 每个Activity都需要创建整个布局视图对象, 一个是代码量更大,
另一个不易实现复用(布局是可以轻松实现复用的), 还有就是修改更麻烦
2). 如果不用Mode层(实体Mode)?
问题: 当应用一个界面需要展示或处理很多数据时, 对应的实体类是必不可少的
3). 如果不用Mode层(非实体Mode)?
问题: 那需要将所有的逻辑处理的代码都写到Activity中, 一个使Activity变得太臃肿,
另一个无法复用业务逻辑功能代码

MVC优点:

  • 耦合性低,视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码。
  • 重用性高
  • 生命周期成本低
  • MVC使开发和维护用户接口的技术含量降低
  • 可维护性高,分离视图层和业务逻辑层也使得WEB应用更易于维护和修改
  • 部署快。

MVC缺点:

  • 存在问题是Controller层和View层的划分不明显,Model层和View层的存在耦合。
    不适合小型,中等规模的应用程序,花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失。
    视图与控制器间过于紧密连接,视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
    视图对模型数据的低效率访问,依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。

MVP

来源

是MVC进一步演化出来的,由Microsoft的Martin Fowler提出。
这个模式被普遍的引用于ASP.NET Web Forms 应用程序。并且也应用于windows form。

1 什么是MVP ?

  • Model层代表了描述业务逻辑和数据的一系列类的集合。它也定义了数据修改和操作的业务规则。
  • View代表了UI组件,像CSS,JQuery,html等。他只负责展示从Presenter接收到的数据。也就是把模型(译者注:非Modle层模型)转化成UI。
  • Presenter负责处理View背后所有的UI事件。它通过View接收用户输入,之后利用Model来处理用户的数据,最后把结果返回给View。与View和Controller不同,View和Presenter之间是完全解耦的,他们通过接口来交互。另外,presenter不像controller处理进入的请求。

2. 理解

1.结构图
设计模式MVC、MVP、MVVM_第2张图片

Model层和View层之间不能有交互,要通过Presenter层进行交互,其中View层和Presenter层是通过接口进行交互,可以定义Contract(契约)接口来指定View层和Presenter之间的契约

  • 注意 三层之间调用顺序为view->presenter->model,为了调用安全着想不可反向调用!不可跨级调用!

3.MVP特点

M、V、P之间双向通信。
View 与 Model 不通信,都通过 Presenter 传递。Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现。
View 非常薄,不部署任何业务逻辑,称为”被动视图”(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以保持Presenter的不变,这样就可以重用。不仅如此,还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试–从而不需要使用自动化的测试工具。

缺点:内存泄露
在MVP模式中,内存泄漏的主要原因是由于当前View层(如Activity或者Fragment)在卸载时,Model层中仍有业务没有结束(如子线程未完成、网络请求超时等),而这里的Presenter层中拥有Mode层和View层的引用,所以Presenter层也暂时无法释放,最终导致View的引用也没有释放,我们的Activity或者Fragment就算时销毁了,GC也无法回收它们,因为还有引用在指向它们呢。

注意:
在MVP中,View层不会部署任何的业务逻辑,从而比较薄,它被称为被动视图(Passive View),意思是它没有任何的主动性,而且这样的设计也方便做单元测试,但是也会有如下问题:

  1. 尽管减少了View层的代码,但是随着业务的复杂度不断提高,Presenter层的代码也会变得越来越臃肿。
  2. View层和Presenter层是通过接口交互的,随着业务的复杂度不断提高,接口数量会大量增加。
  3. 如果View层更新的话,就像UI的输入和数据的变化,都需要主动去调用Presenter层的代码,缺乏自动性和监听性。
  4. MVP是以UI和事件为驱动的传统模型,更新UI需要保证能持有控件的引用,而且更新UI需要考虑Activity或者Fragment的生命周期,防止内存泄漏。

设计模式MVC、MVP、MVVM_第3张图片
上图中说明了低层的不会直接给上一层做反馈,而是通过 View 、 Callback 为上级做出了反馈,这样就解决了请求数据与更新界面的异步操作。上图中 View 和 Callback 都是以接口的形式存在的

MVVM

MVVM即Model-View-View Model。这个模式提供对View和View Model的双向数据绑定。这使得View Model的状态改变可以自动传递给View。典型的情况是,View Model通过使用obsever模式(观察者模式)来将View Model的变化通知给model。

MVVM(Model-View-ViewModel)是MVP进一步演化出来的,它也是由Microsoft的Martin Fowler提出
这个模式被广泛应用于WPF,Silverlight,Caliburn,nRoute 等。

1.什么是MVVM?

01.Model:代表了描述业务逻辑和数据的一系列类的集合。它也定义了数据修改和操作的业务规则。
02.View:代表了UI组件,像CSS,JQuery,html等。他只负责展示从Presenter接收到的数据。也就是把模型转化成UI。
03.View Model:负责暴漏方法,命令,其他属性来操作VIew的状态,组装model作为View动作的结果,并且触发view自己的事件。

MVVM模式关键点:

  1. 用户和View交互。
  2. View和ViewModel是多对一关系。意味着一个ViewModel只映射多个View。
  3. View持有ViewModel的引用,但是ViewModel没有任何View的信息。
  4. View 和ViewModel之间有双向数据绑定关系。

2.理解

1.结构图
设计模式MVC、MVP、MVVM_第4张图片

  • Model(数据层):负责处理数据逻辑。
  • View(视图层):负责处理视图显示,在Android中使用xml或者Java/Kotlin代码去实现视图,Activity和Fragment承担了此层的责任。
  • ViewModel:负责连接Model层和View层,是这两层的中间纽带,负责处理业务逻辑,View层和ViewModel层是双向绑定的,View层的变动会自动反映在ViewModel层,ViewModel层的变动也会自动反映在View层。

使用MVVM后,每一层的职责也更加清晰了,也方便做单元测试,同时因为View层和ViewModel层是双向绑定,开发者不需要再去主动处理部分逻辑了,减少了不少胶水代码,如果使用了一些数据绑定的库,例如在Android中的DataBinding,可以减少更加多的胶水代码。

MVC和MVP的区别是什么?

MVP是MVC的进一步解耦,简单来讲,在MVC中,View层既可以和Controller层交互,又可以和Model层交互;而在MVP中,View层只能和Presenter层交互,Model层也只能和Presenter层交互,减少了View层和Model层的耦合,更容易定位错误的来源。

MVVM和MVP的最大区别在哪?

MVP中的每个方法都需要你去主动调用,它其实是被动的,而MVVM中有数据驱动这个概念,当你的持有的数据状态发生变更的时候,你的View你可以监听到这个变化,从而主动去更新,这其实是主动的。

ViewModel如何知道View层的生命周期?

事实上,如果你仅仅使用ViewModel,它是感知不了生命周期,它需要结合LiveData去感知生命周期,如果仅仅使用DataBinding去实现MVVM,它对数据源使用了弱引用,所以一定程度上可以避免内存泄漏的发生。

ViewModel 中postValue与setValue区别?

setValue 只能在主线程调用,同步更新数据
postValue 可在后台线程调用,其内部会切换到主线程调用 setValue

postValue 收不到通知

postValue 使用不当,可能发生接收到数据变更的通知:

If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.

如上,源码的注释中明确记载了,当连续调用 postValue 时,有可能只会收到最后一次数据更新通知。

原因:

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

mPendingData 被成功赋值 value 后,post 了一个 Runnable

mPostValueRunnable 的实现如下:

private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked")
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};

postValue 将数据存入 mPendingData,mPostValueRunnable 在UI线程消费mPendingData。

在 Runnable 中 mPendingData 值还没有被消费之前,即使连续 postValue , 也不会 post 新的 Runnable

mPendingData 的生产 (赋值) 和消费(赋 NOT_SET) 需要加锁

这也就是当连续 postValue 时只会收到最后一次通知的原因。

链接

浅谈 MVP in Android
如何更高效的使用MVP以及官方MVP架构解析
Android MVP架构搭建
Android简单实用的MVP框架
Android MVP模式 入门
一步一步带你认识 MVP+Retrofit+Rxjava 并封装(一)
一步一步带你认识 MVP+Retrofit+Rxjava 并封装(二)
Android架构设计–MVP模式第(二)篇,如何减少类爆炸
Android 中的 MVP 模式(带实例)
Android MVP架构的自述
优化你的代码结构 — MVP
灵活利用泛型的MVP模式T-MVP(附带一个快速创建MVP接口的Android Studio插件-TMVPHelper)
高级MVP架构封装演变全过程
Android 滑动选择控件 & MVP+Retrofit+RxJava资源推荐
Android MVP && MVVM深度解析
巧用MVVM搭建GitHub客户端
正确认识 MVC/MVP/MVVM
关于MVC/MVP/MVVM的一些错误认识
MVC、MVP、MVVM,谈谈我对Android应用架构的理解
从google todo-mvp示例再次学习MVP
MVVM,RxJava和Retrofit的一次实践
MVVM设计模式之Data Binding库的使用
Android开发之MVVM新姿势探索
分享一个我开发的MVVM架构的开源小项目
MVVMLin一个基于Jatpack+Kotlin+协程+Retrofit的快速开发框架
犹豫要不要用DataBinding?这篇文章帮你解惑
一款高仿 Eyepetizer | 开眼短视频的 MVVM 开源项目
关于 Android MVVM 一些理解与实践
Android 架构探索,MVVM 原来如此简单!
MVVM+组件化+Arouter实现
Android Kotlin+Jetpack+MVVM
Kotlin协程与JetPack组件初探
Jetpack MVVM七宗罪 之一 :还在使用 Fragment 作为 LifecycleOwner ?
爱了爱了!我理解的Android中MVVM架构模式!
MVVM中LiveData与Flow最佳实践!
彻底理解Android架构,重构Jetpack MVVM!
浅谈Android开发中的MVVM模式
MVVM 进阶版:MVI 架构了解一下
浅尝MVI
MVI 架构封装:快速优雅地实现网络请求
在两个商业App中使用MVI后,我…
项目 todo-mvp
项目MVPArms

你可能感兴趣的:(设计模式,android,MVC,MVP,MVVM)