iOS--MVC,MVP和MVVM

2021-06-16  本文已影响0人  mayuee

MVC

MVC,是模型(Model)-视图(View)-控制器(Controller)的缩写,其特点是:M和V相互隔离,通过C连接。

MVC

MVC分工

MVC通信

MVC总结

MVCS

苹果自身就采用的是这种架构思路,从名字也能看出,也是基于MVC衍生出来的一套架构。从概念上来说,它拆分的部分是Model部分,拆出来一个Store。这个Store专门负责数据存取。但从实际操作的角度上讲,它拆开的是Controller。

MVCS如何分工

这算是瘦Model的一种方案,瘦Model只是专门用于表达数据,然后存储、数据处理都交给外面的来做。MVCS使用的前提是,它假设了你是瘦Model,同时数据的存储和处理都在Controller去做。所以对应到MVCS,它在一开始就是拆分的Controller。因为Controller做了数据存储的事情,就会变得非常庞大,那么就把Controller专门负责存取数据的那部分抽离出来,交给另一个对象去做,这个对象就是Store。这么调整之后,整个结构也就变成了真正意义上的MVCS。

分工总结:
视图(View):用户界面
控制器(Controller):业务逻辑及处理
模型(Model):数据存储
存储器(Store):数据处理逻辑

MVCS是基于瘦Model的一种架构思路,把原本Model要做的很多事情中的其中一部分关于数据存储的代码抽象成了Store,在一定程度上降低了Controller的压力。

关于胖Model和瘦Model

胖Model (Fat Model)

cell.obj = obj;

胖Model包含了部分弱业务逻辑。胖Model要达到的目的是,Controller从胖Model这里拿到数据之后,不用额外做操作或者只要做非常少的操作,就能够将数据直接应用在View上。

胖Model做了这些弱业务之后,Controller就会降低一些复杂度,只需要关注强业务代码就行了。众所周知,强业务变动的可能性要比弱业务大得多,弱业务相对稳定,所以弱业务塞进Model里面是没问题的。另一方面,弱业务重复出现的频率要大于强业务,对复用性的要求更高,如果这部分业务写在Controller,类似的代码会洒得到处都是,一旦弱业务有修改(弱业务修改频率低不代表就没有修改),这个事情就是一个灾难。如果塞到Model里面去,改一处很多地方就能跟着改,就能避免这场灾难。
然而其缺点就在于,胖Model相对比较难移植,虽然只是包含弱业务,但好歹也是业务,迁移的时候很容易拔出萝卜带出泥。另外一点,MVC的架构思想更加倾向于Model是一个Layer,而不是一个Object,不应该把一个Layer应该做的事情交给一个Object去做。最后一点,软件是会成长的,FatModel很有可能随着软件的成长越来越Fat,最终难以维护。

瘦Model(Slim Model)

cell.textLabel.text = obj.name;
cell.sunTextLabel = obj.sno;

瘦Model只负责业务数据的表达,所有业务无论强弱一律扔到Controller。瘦Model要达到的目的是,尽一切可能去编写细粒度Model,然后配套各种helper类或方法来对弱业务做抽象,强业务依旧交给Controller。
由于瘦Model跟业务完全无关,它的数据可以交给任何一个能处理它数据的Helper或其他的对象,来完成业务。在代码迁移的时候独立性很强。另外,由于瘦Model只是数据表达,对它进行维护基本上是0成本,软件膨胀得再厉害,瘦Model也不会大到哪儿去。

缺点就在于,由于Model的操作会出现在各种地方,瘦Model在一定程度上违背了DRY(Don’t Repeat Yourself)的思想,Controller仍然不可避免在一定程度上出现代码膨胀。

MVP

MVC的缺点在于并没有区分业务逻辑和业务展示, 这对单元测试很不友好。 MVP针对以上缺点做了优化,它将业务逻辑和业务展示也做了一层隔离,对应的就变成了MVCP。M和V功能不变,原来的C现在只负责布局,而所有的逻辑全都转移到了P层。

MVP中的V在iOS中指的是ViewController和View。MVP将MVC的Controller进行拆分:视图数据逻辑处理部分为P,Controller剩余部分与View合并成V。V和P之间通过Protocol进行通信。

视图数据逻辑:与视图相关的数据处理。例如将NSDate转换成NSString

MVP

MVP实现了各模块的解藕,具有更好的可测试性。但是总体代码量比MVC大。另外,iOS MVC更适用于快速开发,即代码规模较小的项目。因此将简单的MVC的Demo改成MVP,反而会显得笨拙。

这看起来不正是苹果所提出的MVC方案吗?确实是的,这种模式的名字叫做MVC,但是,这就是说苹果的MVC实际上就是MVP了?不,并不是这样的。如果你仔细回忆一下,View是和Controller紧密耦合的,但是MVP的协调器Presenter并没有对ViewController的生命周期做任何改变,因此View可以很容易的被模拟出来。在Presenter中根本没有和布局有关的代码,但是它却负责更新View的数据和状态。

MVP如何分工

MVP是第一个如何协调整合三个实际上分离的层次的架构模式,既然我们不希望View涉及到Model,那么在显示的View Controller(其实就是View)中处理这种协调的逻辑就是不正确的,因此我们需要在其他地方来做这些事情,比如用户输入操作,数据请求,数据处理等等业务逻辑。

分工总结:
视图(View):用户界面
模型(Model):数据存储
展示器(Presenter):数据处理,业务逻辑。

View和Presenter之间是完全解耦的,他们通过接口来交互
View和Presenter是一对一关系,意味着一个Presenter只映射一个View,且他们之间是可以双向交互的。

MVP 总结

MVVM

在MVP的基础上,将P改成与V双向绑定的VM就变成了MVVM。

image

绑定是一种响应式的通信方式。View拥有ViewModel并监听ViewModel中变量值得变化,当ViewModel某个值变化时,View对象会感知并作出相应展示。可以使用KVO和RAC实现。例如在Label中显示倒计时,是V绑定了包含定时器的VM。
双向绑定在MVVM中指的是V和VM之间相互绑定。例如TextField的text长度达到阈值,另一个Button改变背景颜色。这个过程中首先VM感知V中TextField的text属性长度变化,V感知VM中对应的状态属性。一旦V中TextField的text属性长度超出VM中的阈值,VM中的状态属性改变,触发V中Button的背景色发生改变。

MVVM

MVVM 是 MVC 模式的一种演进,它主要解决了 ViewController 过于臃肿带来的不易维护和测试的问题。其中 ViewModel 的主要职责是处理业务逻辑并提供 View 所需的数据,这样 VC 就不用关心业务,自然也就瘦了下来。ViewModel 只关心业务数据不关心 View,所以不会与 View 产生耦合,也就更方便进行单元测试。

View 是一个壳,它所呈现的内容都需要由 ViewModel 来提供,而 View 又不与 ViewModel 直接沟通,这时就需要 ViewController 来做中间的协调者。

ViewController 持有 View 和 ViewModel,当 VC 初始化时,会让 ViewModel 去取数据,简单来说就是调用 VM 的某个获取数据的方法。

严格来说MVVM其实是MVCVM。从图中可以得知,Controller夹在View和ViewModel之间做的其中一个主要事情就是将View和ViewModel进行绑定。在逻辑上,Controller知道应当展示哪个View,Controller也知道应当使用哪个ViewModel,然而View和ViewModel它们之间是互相不知道的,所以Controller就负责控制他们的绑定关系,所以叫Controller/控制器就是这个原因。
归根结底就是一句话:在MVC的基础上,把C拆出一个ViewModel专门负责数据处理的事情,就是MVVM。然后,为了让View和ViewModel之间能够有比较松散的绑定关系,于是我们使用ReactiveCocoa,因为苹果本身并没有提供一个比较适合这种情况的绑定方法。iOS领域里KVO,Notification,block,delegate和target-action都可以用来做数据通信,从而来实现绑定,但都不如ReactiveCocoa提供的RACSignal来的优雅,如果不用ReactiveCocoa,绑定关系可能就做不到那么松散那么好,但并不影响它还是MVVM。

MVVM如何分工

视图(View)层:用户界面,视图展示。包含UIView以及UIViewController,View层是可以持有ViewModel的。
ViewModel层:视图适配器。暴露属性与View元素显示内容或者元素状态一一对应。一般情况下ViewModel暴露的属性建议是readOnly的。还有一点,ViewModel层是可以持有Model的。
Model层:数据模型与持久化抽象模型。数据模型很好理解,就是从服务器拉回来的JSON数据。而持久化抽象模型暂时放在Model层,是因为MVVM诞生之初就没有对这块进行很细致的描述。按照经验,我们通常把数据库、文件操作封装成Model,并对外提供操作接口。(有些公司把数据存取操作单拎出来一层,称之为DataAdapter层,所以在业内会有很多MVVM的变种,但其本质上都是MVVM)。
Binder:MVVM的灵魂。可惜在MVVM这几个英文单词中并没有它的一席之地,它的最主要作用是在View和ViewModel之间做了双向数据绑定。如果MVVM没有Binder,那么它与MVC的差异不是很大。

因为View、ViewModel以及Model间的清晰的持有关系,所以在三个模块间的数据流转有了很好的控制。

MVVM模式特点

MVVM 总结

选择

  1. 越复杂的框架耦合度越小,但是开发速度越慢,反之亦然。所以要根据具体项目需求,在不同阶段决定框架。
  2. 如果模式之间存在兼容性,可选择混合开发。

原文https://www.jianshu.com/p/6460021c81a4

分层架构

如按照数据层、网络层、业务层、界面层分层架构

MVC、MVP、MVVM都属于界面层

上一篇 下一篇

猜你喜欢

热点阅读