重学架构

前言

当我们开发一款应用,选择什么架构一直是个老大难的问题,有的小伙伴可能提议使用MVC,MVP,MVVM或者混搭,更有甚者一把梭全部写在一堆,也有一种情况是什么目前架构流行就使用什么方案(我就是这样,哈哈), 当真正执行时,每个人都有自己的架构,最终结果就是代码混乱不堪,后续难以维护,这些归咎于对架构理解不够全面,查询了很多资料后,对架构有了新的理解

带着疑问思考

  1. 什么是表现层分离?

  2. Model是否等于实体?

  3. 业务逻辑应该写在哪?

  4. 不同层进行通信的Model对象是否需要转换?

  5. MVC,MVP,MVVM之间有何关系?

MVC:表现层分离

MVC应该是我们每个人第一个接触的架构,也是我们理解其他架构的基础

MVC = Model-View-Controller

字面就可以看出MVC将应用程序划分为三种角色

  • Model 层 :主要管理业务模型和行为,它既保存程序的数据,也定义了处理该数据的逻辑

  • View层:接受用户的交互请求,展示数据信息给用户

  • Controller:主要担任Model与View之间的桥梁,用于控制程序的流程

传统MVC

来张图

该版本的 MVC 其实可以看成是由三个基本设计模式组合而成:组合模式、策略模式、观察者模式。组合模式前面已经讲过,就是用在了 View 层。View 与 Controller 之间则用了策略模式,Controller 对象为一个或多个 View 对象实现了策略,View 对象仅限于保持其视觉外观,而与程序逻辑相关的所有决策都委托给 Controller,即 View 可以使用不同的 Controller 实现,得到不同的行为。Model 与 View 之间则使用了观察者模式,View 会注册为 Model 的观察者,当 Model 有变化的时候,就能通知到 View。

所以,一般的交互流程就是:

  1. 用户操纵 View,接着生成一个事件。比如用户点击某个按钮,则会生成一个点击事件。

  2. Controller 对象接收事件并解释该事件,即,它应用了策略。该策略可以是请求 Model 对象以更改其状态,或请求 View 以更改其行为或外观。比如,一个注册按钮产生的事件被 Controller 接收之后,那它就会解释该事件,可能先校验用户的输入是否为空,如果为空则请求 View 提示让用户填写用户名和密码等;如果校验通过,那就请求 UserModel 创建新用户。

  3. 当状态改变时,Model 对象又通知所有已注册为观察者的对象。如果观察者是 View 对象,则可以相应地更新其外观或行为。还是上面的例子,UserModel 创建新用户成功后,就可以通知观察者们,相应的 View 对象接收到 UserModel 创建新用户成功的通知后,就可以跳转到注册成功后的页面了。

看到这个图时,View和Controller都好理解,但是为啥View要监听Model对象的变化,而且View还可以调用Model 查阅资料发现MVC有两种模式主动模式和被动模式,移动开发主要使用的是被动模式(去掉Notify),并且将View和Model彻底解耦,统一通过Controller实现数据的传递

也就演变成

Android中的MVC

先上图

不过,在 App 的实际应用中,又是另一种交互结构。出现了一个 ViewController(Activity/Fragment) 角色,不止承担 Controller 的职责,也承接了部分 View 的职责,主要包括对 View 的生命周期管理和数据填充等,而原本的 View 角色就只剩下展示的功能。这种方式的主要优点就是 View 变轻了,可复用性更高了;但缺点也很明显,原本的 Controller 是很轻的,但现在的 ViewController 则是很重的,承担了太多职责。

很大部分人认为Controller中应该写业务逻辑,Model只是个数据模型,所以很自然的将View和Model中的代码移到Activity和Fragment中,尤其是一把梭的小伙伴,这时候会代码变得极其臃肿难以维护,从而偏离了MVC的初衷分层思想

正确的写法应该减少ViewController的职责,合理分层

还是来张图

是不是觉得这个图很熟悉,将Controller改成Presenter ,这不就是MVP吗,其实MVC的Controller和MVP的Presenter是一个东西,仅仅为了和MVC区分开来

MVP:面向接口编程

MVP = Model-View-Presenter

MVP和MVC的区别就是将Activity和Fragment的职责进一步缩小,仅仅当成一个View,并且通过接口解耦,是组件减少依赖

MVP通过接口降低耦合的同时,当然需要额外写一些代码,但总归利大于弊

MVVM:数据驱动和双向绑定

MVVM = Model-View-ViewModel

与MVC,MVP不同,建立Model和VIew的桥梁换成了ViewModel

ViewModel

Model和ViewModel的区别?

Model封装的是业务逻辑和数据,管理的是业务模型

ViewModel = Model of VIew ,管理的视图模型,封装的是视图的表示逻辑和数据,是视图的抽象,包裹视图的属性和命令,或者视图的状态和行为

数据绑定

单向绑定:ViewModel 与 View 绑定之后,ViewModel 变化后,View 会自动更新,但反之不然,即数据传递的方向是单向的。 (ViewModel —> View)

Android的单向绑定需要DataBinding或者Jetpack套件

双向绑定:ViewModel 与 View 绑定之后,如果 View 和 ViewModel 中的任何一方变化后,另一方都会自动更新,这就是双向绑定。(ViewModel <—> View

Android的双向绑定需要DataBinding来实现的

数据驱动

从图上也可以看出MVVM核心是将数据变化,然后借助Databinding或者其他组件,体现在View上,而不是和MVC,MVP一样通过命令去出发,重点关注的数据,两者有本质的不同

优点

很好的解决显示一致性问题

解决疑问

  1. 什么是表现层分离?

    将视图实现和业务分离

  2. Model是否等于实体?

    Model 层主要管理业务模型的数据和行为,它既保存程序的数据,也定义了处理该数据的逻辑,所以 Model = 数据 + 业务逻辑。因此,处理业务逻辑属于 Model 的职责,而非 Controller。从数据的维度来说,可以细分为数据的定义、数据的存储、数据的获取。数据的定义其实就是定义数据结构,一般用实体类来定义,以方便在不同角色间传递数据。数据的存储和获取则可能有几种途径:数据库、网络或缓存等。因此,在实际应用中,一个 Model 并不只是简单的一个对象,而是一个更广泛的层级。很多时候,会将 Model 层再进行分解,比如应用于客户端程序时,可以将 Model 层再细分为业务逻辑层、网络层、存储层等,而实体类其实只是贯穿其中的一种数据结构而已。不过,狭义上,当我们说一个 Model 对象的时候,主要是对外部组件而言的,更多是指这个 Model 对外所提供的数据,并不关心数据从何而来。这可能就是让很多人将 Model 误认为就是实体类的原因

  3. 业务逻辑应该写在哪?

    有个概念很容易混淆需要理解清楚 业务逻辑=界面交互逻辑+数据逻辑 页面交互逻辑写在表现层对应的Controller,Presenter,ViewModel,数据逻辑写在Model中,而我们常说的业务逻辑指的是数据逻辑

  4. 不同层进行通信的Model对象是否需要转换?

    差异不大,可以直接使用,否则需要进行PO->VO的转化

  5. MVC,MVP,MVVM之间有何关系?

    MVP可以看成MVC ,更加解耦,分层更加合理的升级架构

    MVVM 和MVP并没有关系,不是MVP+Databinding = MVVM ,一个是数据驱动,一个是命令驱动,两者本质不同,各自解决不同的场景

总结

  1. 三种架构都是为了将表现层和业务分离,只是解耦方式不一样

  2. MVVM强调的是数据驱动,解决一致性问题

  3. MVP 是面向接口编程

  4. MVVM和MVP没有谁更好的问题,看各自的使用场景合理使用

  5. Model = 数据 + 业务逻辑,不是简单的Model类,Model类只是贯穿层之间的一种数据结构,

  6. 处理业务逻辑属于 Model 的职责,而非 Controller

参考

正确认识 MVC/MVP/MVVM

关于Android架构,你是否还在生搬硬套?

白话 MVC、MVP、MVVP

猜你喜欢

转载自juejin.im/post/7048698561042579486
今日推荐