前言
相信很多iOS开发者从学习iOS开始就是用的MVC架构,因为Apple推荐使用MVC,原因:上手快,且开发效率高。但是在开发过程中求速度,并没有严格的遵守MVC原则,随着APP的不断更新迭代,导致了Controller变成了集Model,View,Controller的一个大集合,代码维护也变得很难受,网络请求,数据存储和处理,业务逻辑,用户交互等基本都是在控制器里面处理,以致几千行的控制器屡见不鲜,这样既不好查找bug,也不利于单元测试。所以我去重新认识了一下MVC,也去学习了一下MVP以及MVVM。
基本要素
- ** Models(模型)**:
数据层
,一般用来承载数据,以及数据处理 -
Views (视图):
展示层
,将数据以UI的形式展示 -
Controller/Persenter/ViewModel(控制器/展示器/视图模型):
业务层
,它又是Model跟View之间的粘合剂,一般来说,当用户对View操作时它去负责修改相应的Model,当Model的值发生变化时它去负责更新对应的View。
上面提到的数据层
,展示层
,业务层
,其实就是针对模块分类而言的三层架构
;而MV(X)这种层次划分,主要是针对数据流动的方向而言的。
MVC
一个标准的MVC它的结构及交互是这样的
当View接收到用户操作指令时,View移交给Controller处理,Controller去更新Model,Model更新之后通知Controller,控制器再去更新View。我们可以看到:
- Model它需要提供数据给Controller,所以它不仅要负责拉取数据和处理数据还要提供数据存取的接口,并不只是一个数据表达对象,它承担的事情会很多,由此可见它是一个胖Model。
- View的更新是通过暴露的接口或元素交给Controller来执行的,而不是直接把Model丢给View;这样虽然会增加Controller的代码量,但是也让View变得很纯洁,只需要展示界面元素,以及本身的动画效果,所以View跟Model是完全分开的,利于View的复用以及UI的修改。
- Controller不负责View的布局及展示逻辑,它只负责监听 View 层的事件,从Model取数据(如果需要),再去更新View。但是由于UIViewController的设计特殊,它本身自带一个View,所以导致很多开发者直接在Controller上进行View布局及展示逻辑,导致了Controller越来越重,很明显这违背了MVC的思想。我理解的做法是分一个主View出来,在这上面去做View的事情,但是这也多了一层事件的传递(这个主View先要接管它上面控件的事件回调,再一一暴露给Controller)。
上面提到了胖Model,其实就是指Model做的事情较多,包含了一些弱业务,Controller从Model中拿到的数据,不用做额外的或者非常少的处理,就可以直接应用在View上;那么相应的就有瘦Model,它仅仅只是表达数据的作用。说到这里那么就顺便提一下MVCS架构模式,它也是MVC的一个变种,从Model中拆出一个Store,专门负责数据拉取和处理,而原来那个胖Model也变成了瘦Model,只是用来承载数据,这样Model的维护成本就会变得很低。因为变化也不是很大,就不单独拿出来说了。
小结
我觉得在Controller非常臃肿的问题上,MVC不应该背这个锅!,只是开发者没有严格按照MVC的原则来使用。那么为什么又会衍生出各种架构模式,我觉得问题还是在Controller上,因为iOS中Controller叫做UIViewController,尽管我们可以分出一个主View出来做布局及展示逻辑,但是它毕竟自带一个View且管理着它们的生命周期(viewWillAppear,viewWillDisappear等等),所以C跟V之间的联系还是过于紧密。
MVP
还是先看图吧,毕竟一图胜千言!
我们发现MVP跟MVC数据流向的方式是一致的,只是流向的对象有点不一样。那么实质上做了什么改变呢?
- 多出一个Presenter对象,它来扮演View跟Model的协调者,取代了MVC中Controller,变成了整个架构中的大脑,而且不关注View/Controller的生命周期,所以它的职责更加明确。
- 在上面也说了MVC中V跟C的联系过于紧密,那好,在MVP中我们就把Controller跟View统一当做View来对待,他们都只负责UI布局及展示逻辑,并将交互事件传递给Persenter处理,所以相比之下模块划分更加清晰。
- View是持有Presenter的,用户交互事件可以直接传给Presenter,而View的更新是通过实现事先定义好的协议,然后由Presenter处理完数据再发起执行的,所以View跟Presenter是一对一的关系。
小结
MVP跟MVC他们的区别就是,MVP把Controller当做一个View来看待,因为它们本身的联系就很紧密,从而避免了Controller的职责模糊。另外View跟Presenter有一层协议关系,所以代码量相对来说也会增加。
MVVM
我们又发现MVVM跟MVP很相似:
- 它们都是将Controller当做一个View来处理,上层通过给View分配一个ViewModel/Presenter来做协调工作以及业务逻辑,很好的避免了视图展示跟业务逻辑的耦合。
不同的是:
- View跟ViewModel之间做了双向绑定,ViewModel绑定了View的用户行为,View绑定了ViewModel的数据。什么意思?就是当View接收到用户行为时,ViewModel可以监听到,然后去做相关逻和数据处理;当ViewModel的数据变化时,View一样可以监听到,然后自己来刷新数据。
- 这里的View不像MVP的Passive View(被动的View)只能被动的去更新数据,它是通过监听ViewModel的数据变化,然后自己更新数据的。这样从
用户交互
->数据处理
->界面更新
就变得自动化。
小结
ViewModel的职责之一就是作为一个表现视图显示自身所需要的静态模型,它有收集,解释和转换那些数据的责任。另外,绑定可以通过KVO来实现,但是有点笨重,可以使用FBKVOController,其实更多的还是通过RAC来做,更能体现MVVM的精髓,也简化了很多的代码。
总结
不管是什么架构模式,他们都是围绕着用户交互
->数据处理
->界面更新
来进行的,只是各自的方式不一样。