MVC、MVP、MVVM

iOS MVC 示意图

这里写图片描述

MVC 的几个明显的特征和体现:

1、View 上面显示什么东西,取决于 Model。Model和View永远不能相互通信,只能通过Controller传递。

2、Model通过Notification和KVO机制与Controller间接通信。只要 Model 数据改了,View 的显示状态会跟着更改。

3、Controller可以直接与View对话(通过outlet,直接操作View,outlet直接对应到View中的控件),View通过 action向Controller报告事件的发生(如用户Touch我了)。Controller是View的直接数据源(数据很可能是 Controller从Model中取得的)。有时候Controller需要实时监控View的状态,这时Controller会通过protocol将其自身设为View的delegate,这样当View will change、should change、did change 的时候Controller也会接到相应通知。
View不存储数据,但View可以通过协议获取Controller而不是Model中的数据用来展示。
Control 负责初始化 Model,并将 Model 传递给 View 去解析展示。

1)Modal 模型对象:

模型对象封装了应用程序的数据,并定义操控和处理该数据的逻辑和运算。例如,模型对象可能是表示商品数据 list。用户在视图层中所进行的创建或修改数据的操作,通过控制器对象传达出去,最终会创建或更新模型对象。模型对象更改时(例如通过网络连接接收到新数据),它通知控制器对象,控制器对象更新相应的视图对象。

2)View 视图对象:

视图对象是应用程序中用户可以看见的对象。视图对象知道如何将自己绘制出来,可能对用户的操作作出响应。视图对象的主要目的就是显示来自应用程序模型对象的数据,并使该数据可被编辑。尽管如此,在 MVC 应用程序中,视图对象通常与模型对象分离。

在iOS应用程序开发中,所有的控件、窗口等都继承自 UIView,对应 MVC 中的 V。UIView 及其子类主要负责 UI 的实现,而 UIView 所产生的事件都可以采用委托的方式,交给 UIViewController 实现。

3)Controller 控制器对象:

在应用程序的一个或多个视图对象和一个或多个模型对象之间,控制器对象充当媒介。控制器对象因此是同步管道程序,通过它,视图对象了解模型对象的更改,反之亦然。控制器对象还可以为应用程序执行设置和协调任务,并管理其他对象的生命周期。

控制器对象解释在视图对象中进行的用户操作,并将新的或更改过的数据传达给模型对象。模型对象更改时,一个控制器对象会将新的模型数据传达给视图对象,以便视图对象可以显示它。

对于不同的 UIView,有相应的 UIViewController,对应 MVC 中的 C。例如在 iOS 上常用的 UITableView,它所对应的 Controller 就是UITableViewController。

苹果推荐的 MVC – 愿景

这里写图片描述

Cocoa MVC

1、由于 Controller 是一个介于 View 和 Model 之间的协调器,所以 View 和 Model 之间没有任何直接的联系。Controller 是一个最小可重用单元,这对我们来说是一个好消息,因为我们总要找一个地方来写逻辑复杂度较高的代码,而这些代码又不适合放在 Model 中。

2、理论上来讲,这种模式看起来非常直观,但你有没有感到哪里有一丝诡异?你甚至听说过,有人将 MVC 的缩写展开成 (Massive View Controller),更有甚者,为 View controller 减负也成为 iOS 开发者面临的一个重要话题。如果苹果继承并且对 MVC 模式有一些进展,所有这些为什么还会发生?

苹果推荐的 MVC – 事实

这里写图片描述

Realistic Cocoa MVC

Cocoa 的 MVC 模式驱使人们写出臃肿的视图控制器,因为它们经常被混杂到 View 的生命周期中,因此很难说 View 和 ViewController 是分离的。尽管仍可以将业务逻辑和数据转换到 Model,但是大多数情况下当需要为 View 减负的时候我们却无能为力了,View 的最大的任务就是向 Controller 传递用户动作事件。ViewController 不再承担一切代理和数据源的职责,通常只负责一些分发和取消网络请求以及一些其他的任务。

你可能会看见过很多次这样的代码:

BookModel *bookModel = [myDataArray objectAtIndex:indexPath.row];
[cell configWithModel:bookModel];

1、这个 cell,正是由 View 直接来调用 Model,所以事实上 MVC 的原则已经违背了,但是这种情况是一直发生的甚至于人们不觉得这里有哪些不对。如果严格遵守 MVC 的话,你会把对 cell 的设置放在 Controller 中,不向 View 传递一个 Model 对象,这样就会大大减少 Controller 的体积。Cocoa 的 MVC 被写成 Massive View Controller 是不无道理的。

2、直到进行单元测试的时候才会发现问题越来越明显。因为你的 ViewController 和 View 是紧密耦合的,对它们进行测试就显得很艰难–你得有足够的创造性来模拟 View 和它们的生命周期,在以这样的方式来写 View Controller 的同时,业务逻辑的代码也逐渐被分散到 View 的布局代码中去。

MVC 自身的不足:

1)MVC 在现实应用中的不足:

在 MVC 模式中 view 将用户交互通知给控制器。view 的控制器通过更新 Model 来反应状态的改变。Model(通常使用 Key-Value-Observation)通知控制器来更新他们负责的 view。大多数 iOS 应用程序的代码使用这种方式来组织。
2)愈发笨重的 Controller:

在传统的 app 中模型数据一般都很简单,不涉及到复杂的业务数据逻辑处理,客户端开发受限于它自身运行的的平台终端,这一点注定使移动端不像 PC 前端那样能够处理大量的复杂的业务场景。然而随着移动平台的各种深入,我们不得不考虑这个问题。传统的 Model 数据大多来源于网络数据,拿到网络数据后客户端要做的事情就是将数据直接按照顺序画在界面上。随着业务的越来越来的深入,我们依赖的 service 服务可能在大多时间无法第一时间满足客户端需要的数据需求,移动端愈发的要自行处理一部分逻辑计算操作。这个时间一惯的做法是在控制器中处理,最终导致了控制器成了垃圾箱,越来越不可维护。

控制器 Controller 是 app 的 “胶水代码”,协调模型和视图之间的所有交互。控制器负责管理他们所拥有的视图的视图层次结构,还要响应视图的 loading、appearing、disappearing 等等,同时往往也会充满我们不愿暴露的 Model 的模型逻辑以及不愿暴露给视图的业务逻辑。这引出了第一个关于 MVC 的问题…

视图 view 通常是 UIKit 控件(component,这里根据习惯译为控件)或者编码定义的 UIKit 控件的集合。进入 .xib 或者 Storyboard 会发现一个 app、Button、Label 都是由这些可视化的和可交互的控件组成。View 不应该直接引用 Model,并且仅仅通过 IBAction 事件引用 controller。业务逻辑很明显不归入 view,视图本身没有任何业务。

厚重的 View Controller 由于大量的代码被放进 viewcontroller,导致他们变的相当臃肿。在 iOS 中有的 view controller 里绵延成千上万行代码的事并不是前所未见的。这些超重 app 的突出情况包括:厚重的 View Controller 很难维护(由于其庞大的规模);包含几十个属性,使他们的状态难以管理;遵循许多协议(protocol),导致协议的响应代码和 controller 的逻辑代码混淆在一起。

厚重的 view controller 很难测试,不管是手动测试或是使用单元测试,因为有太多可能的状态。将代码分解成更小的多个模块通常是件好事。

3)太过于轻量级的 Model:

早期的 Model 层,其实就是如果数据有几个属性,就定义几个属性,ARC 普及以后我们在 Model 层的实现文件中基本上看不到代码(无需再手动管理释放变量,Model 既没有复杂的业务处理,也没有对象的构造,基本上 .m 文件中的代码普遍是空的);同时与控制器的代码越来厚重形成强烈的反差,这一度让人不禁对现有的开发设计构思有所怀疑。
4)遗失的网络逻辑:

苹果使用的 MVC 的定义是这么说的:所有的对象都可以被归类为一个 Model,一个 view,或是一个控制器。就这些,那么把网络代码放哪里?和一个 API 通信的代码应该放在哪儿?

你可能试着把它放在 Model 对象里,但是也会很棘手,因为网络调用应该使用异步,这样如果一个网络请求比持有它的 Model 生命周期更长,事情将变的复杂。显然也不应该把网络代码放在 view 里,因此只剩下控制器了。这同样是个坏主意,因为这加剧了厚重控制器的问题。那么应该放在那里呢?显然 MVC 的 3 大组件根本没有适合放这些代码的地方。

5)较差的可测试性

MVC 的另一个大问题是,它不鼓励开发人员编写单元测试。由于控制器混合了视图处理逻辑和业务逻辑,分离这些成分的单元测试成了一个艰巨的任务。大多数人选择忽略这个任务,那就是不做任何测试。

上文提到了控制器可以管理视图的层次结构;控制器有一个 “view” 属性,并且可以通过 IBOutlet 访问视图的任何子视图。当有很多 outlet 时这样做不易于扩展,在某种意义上,最好不要使用子视图控制器(child view controller)来帮助管理子视图。在这里有多个模糊的标准,似乎没有人能完全达成一致。貌似无论如何,view 和对应的 controller 都紧紧的耦合在一起,总之,还是会把它们当成一个组件来对待。Apple 提供的这个组件一度以来在某种程度误导了大多初学者,初学者将所有的视图全部拖到 xib 中,连接大量的 IBoutLet 输出口属性,都是一些列问题。

MVP

C和P的差别

MVP其实两种的:

1、Passive View
2、Supervising Controller

网上绝对部分谈论MVP的文章谈论的其实都是Passive View,这里放上一张Passive View的示意图:
这里写图片描述

MVP: the view is in charge. The view, in most cases, creates its presenter. The presenter will interact with the model and manipulate the view through an interface. The view will sometimes interact with the presenter, usually through some interface. This comes down to implementation; do you want the view to call methods on the presenter or do you want the view to have events the presenter listens to? It boils down to this: The view knows about the presenter. The view delegates to the presenter.

view负责。大部分情况下,view创建它自己的presenter。presenter通过接口和model相互作用然后操作这个view。view通常会通过一些接口有时会和presenter相互作用。归结起来实现:你想让view在presenter上调用方法或者想让view监听presenter上的一些事件吗?归结起来:view了解presenter。view是presenter的代理。

MVC: the controller is in charge. The controller is created or accessed based on some event/request. The controller then creates the appropriate view and interacts with the model to further configure the view. It boils down to: the controller creates and manages the view; the view is slave to the controller. The view does not know about the controller.

controller在负责。基于一些事件或者请求,controller被创建或者被存取。然后controller创建合适的view或者和model相互作用创建更深层次的view。归结起来:controller创建和管理view;view受命于controller。view不了解controller。

1、简而言之,MVP是View驱动的,View层持有一个对应Presenter的引用,View上的交互事件首先会调用Presenter提供的接口,然后Presenter调用Model提供的方法取得数据,最后Presenter将取得的数据传递到View上展示.

2、MVC则是由Controller驱动的,Controller持有View,并响应View上的交互事件,根据交互调用不同的Model方法取得反馈数据,再将数据传递给View展示.

我的理解是,MVP是用户视角:所见即View.MVC则是程序员视角:I control everyone.

MVVM的示意图:

这里写图片描述

这里写图片描述

上图展示了MVVM与MVC的差别。

在MVC模式的iOS开发中,Controller承担了太多的代码,包含着我们的视图处理逻辑和业务逻辑。

这里写图片描述

在MVVM中,我们将视图处理逻辑从C中剥离出来给V,剩下的业务逻辑部分被称做View-Model。
使用MVVM模式的iOS应用的可测试性要好于MVC,因为ViewModel中并不包含对View的更新,相比于MVC,减轻了Controller的负担,使功能划分更加合理。

而这些ViewModel的代码并不放在ViewController中,我们的View请求自己的ViewModel来获取所需的数据,ViewController完全归于View。

model层,API请求的原始数据
view层,视图展示,由viewController来控制
viewModel层,负责业务处理和数据转化

http://www.jianshu.com/p/d56cb11ebc84

http://blog.csdn.net/hero_wqb/article/details/50890159

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值