关于MV(X)系列的架构模式的讨论从最初的MVC提出到如今的MVVM都没间断过(VIPER架构模式不作讨论),不一样人对架构模式持有不一样的观点,关于架构模式的博客也不少。从接触MVC开始,再到后面实际的运用,总会存在不少疑问,在面试中也被问倒了,面试官的话深深的触及个人灵魂,痛定思痛,专门花时间去深刻了解这方面的知识。如今对于MV(X)系列的架构模式本人也有本身的见解,写这篇博客除与发表观点,同时算是一次总结。在补充下,文章更多的是从iOS开发角度出发去思考。html
MVC模式最先由Trygve Reenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件架构。MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,而且使程序某一部分的重复利用成为可能。——维基百科前端
MVC模式根据程序中的对象的职责或功能进行分类,分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。MVC是一种复合模式,由多个基本的设计模式组合成。这也是MVC会被称为设计模式的缘由。除了对程序中对象的分类,还规定了它们通讯的方式。面试
V:负责UI展现和事件交互处理设计模式
M:数据存储和数据的处理网络
C:负责V和M的通讯,管理V和M的生命周期。架构
来看下传统MVC的架构图(引用苹果的图): app
当View接收到用户事件时,将事件处理移交至Controller。Controller接收事件后能够请求Model进行数据变动或者请求View去更改行为或者外观。当Model的数据变动的时候,Model通知全部注册的观察者,View收到数据变动通知后,更新View外观。函数
在这种模式下,Controller是View的一个策略,同时还负责View的事件处理,还要负责通知Model更新数据。不一样的View事件不一样,不一样的Model数据更新的接口也不一样,在这种状况下,Controller是很难复用的。能复用的模块只有是View和Model。但从上图中能够看到View和Model存在耦合,View和Model没有彻底隔离。View的更新依赖于Model。为了达到复用的目的,View的更新不该该依赖于Model,应该独立于Controller和Model,同理Model也是独立于Controller和View的。接下来咱们看下苹果理想的MVC模式。oop
苹果理想的MVC,就是将View和Model彻底隔离,View和Model之间不存在耦合,View和Model经过Controller这个中介者进行双方通讯。在这里Controller是中介者模式的一种实现。View在这里也是命令模式的实现,经过Target-action机制,能够将View做为命令的执行者,对应Target。action就是一个的命令。响应链是调度者,负责给合适的执行者下发命令。测试
苹果理想的MVC架构图:
在iOS里面咱们知道有个UIViewController类,ViewController的出现源自苹果为了提升开发效率将View和Controller绑定到一块儿。从实际的使用上能够感受到开发效率获得提升。对于新手快速入门也很方面,由于不须要去考虑任何架构模式,不用去严格的作不一样对象的职责区分,大多数的初学者仍是较习惯于大杂烩式的程序撰写,因此致使Massive Controller的出现。ViewController作的事就变得复杂,负责View和Model的生命周期,负责View和Model的通讯。负责页面跳转,负责网络请求,负责处理数据等。这已经违反了设计模式的单一性原则。随着业务增多项目会变得难以维护。
iOS中的MVC架构图:
即使苹果如此设计,咱们仍是能够实现苹果理想的MVC。咱们须要对ViewController进行瘦身。View的职责不变。业务逻辑抽离到Model中,ViewController中负责View和Model的生命周期,负责View和Model的通讯,负责页面跳转。View将事件处理委托给ViewController,并对外提供更新UI的接口。ViewController,Model处理发起网络请求,处理数据完后通知ViewController。而后ViewController在去更新View。这样保持View和Model的隔离,达到易复用和易测试的效果,同时减轻了ViewController的负担。当业务增多的时候能够添加多个MVC对业务进行划分,避免讲业务代码都写在同一个MVC代码中。
MVC设计提出是为了实现一种动态的程序设计,使后续对程序的修改和扩展简化,而且使程序某一部分的重复利用成为可能,MVC有助于应用程序长远的发展,可扩展性、可维护性和可测试性由于 MVC 的特性而变得容易,MVC对程序中的对象进行了划分,能够对View和Model进行复用。
可是MVC的缺点也很明显,传统的MVC中只有Model能够复用,View更新依赖于Model,View没有独立于Model和Controller,复用可能性小。Controller做为View和Model通讯的通道,处理View提交的事件,同时负责通知Model更新数据等,Controller定制性太高自己就很难复用。从测试角度来讲业务逻辑都放在Controller中就很难测试。在来讲说苹果理想的MVC,这种模式下,Controller也是没法复用的,View和Model的复用性高。测试角度View和Model对外提供了接口,能够经过测试接口判断逻辑和界面更新是否正确。同时Controller须要手动实现View的更新的代码和各类事件代理通讯方法。
在具体的实现中Presenter会持有View的弱引用,不负责管理View生命周期,当Model通知Presenter数据发生变动后,Presenter就能够更新View。为了达到结构的目的,让Presenter不依赖于View,一般结合业务界面定制一个View的协议,抽象出界面更新的方法,而后Presenter持有这个协议的引用,就不用依赖于具体的View。这点是符合设计模式的依赖倒置原则的。同时也能够结合业务抽象出Presenter的行为协议,能够切换不一样的Presenter实现。这里的View是一种策略,Presenter也是一种策略,涉及的是策略设计模式。
使用Passive View或Supervising Controller的决定主要取决于你但愿应用程序的可测试性。若是须要可测试性高,使用Passive View是最合适的,能够经过测试Presenter测试全部的UI逻辑。若是但愿代码简洁而不彻底可测试,选择SuperVising,能够减小编写Presenter中UI更新的代码。
在MVVM以前得先说下MVVM的发展历史,MVVM是马丁·福勒的PM(Presentation Model)架构模式的变体。MVVM和PM都来自MVC模式。MVVM由微软架构师Ken Cooper和Ted Peters开发,经过利用WPF(微软.NET图形系统)和Silverlight(WPF的互联网应用派生品)的特性来简化用户界面的事件驱动程序设计。MVVM也被称为model-view-binder。
PM 模式与 MVP 比较类似,它从视图层中分离了行为和状态,PM以不依赖于特定用户界面平台的方式抽象出视图(建立了视图模型),MVVM以相同的方式抽象出视图的状态和行为。抽象出视图和咱们上面提到的以协议的方式定义个视图模型是一个道理。和Presenter不一样的是PM 模式将视图中的所有状态和行为放到一个单独的展现模型中(PM),协调Model而且为视图层提供一个接口。换句说PM 经过引入展现模型将模型层中的数据与复杂的业务逻辑封装成属性与简单的数据同时暴露给视图,让视图和展现模型中的属性进行同步。
MVVM模式经过Binder层对View和VM完成双向绑定减小手动更新View的代码编写,同时达到View和Model的分离的效果,让它们各司其职。在iOS中Binder层的实现能够经过RAC实现。同时MVVM存在缺点,MVVM的创造者表示实现MVVM的开销对于简单的UI操做是“过分的”,很是大的应用程序中的数据绑定会致使至关大的内存消耗。
从MVC到MVVM,MV(X)系列的架构模式本质上都是从MVC上演化出来的,对程序的对象进行职责区分,减小View和Model之间的耦合提升它们的复用性,为了可测试性能够作进一步的优化。对于不一样的架构模式的选择要根据适合开发平台的模式,苹果推荐使用MVC,安卓使用MVP,前端使用MVVM。固然能够根据项目需求考虑选择更适合的设计模式。不管选择什么架构模式,我以为都要对这些架构模式有所了解,这样才能写出更好的项目。
参考文章