MVC设计模式
概述:Model-View-Controller(MVC),即模型-视图-控制器。它将软件系统分成三大部分: Model,View,Controller三个部分通过某种机制通信。
MVC的职能
M(model)
应用程序的核心,用于处理应用程序数据逻辑部分
V(View)
处理应用程序数据的显示,通常依据Model创建
C(Controll)
处理用户的交互
从视图读取数据,控制用户输入,并向模型发送数据
MVC之间的通信
图解(出自斯坦福大学cs193课程的课件)
这个模式其实应该叫做MCV,用控制器把model与view隔开才对,也就是model与view互相不知道对方的存在,没有任何瓜葛,他们就像一个团队里吵了架的同事,如果有项目需要他俩来参与,那么最好有第三者来管理他俩之间的沟通与协调。这个第三者就是控制器。
既然管理,那么姑且就把这个控制器提做项目经理吧,这样的话让他俩干啥就得干啥。就像斯坦福老头说的视图就是控制器的狗腿子。让我们来欣赏一下这张图
先撇开那些乱七八糟的箭头单看他们之间的分界线,view与controller、model与controller之间的线是虚的,而model与view之间的是双黄线,考过驾照的知道越过这个线意味着什么吧。
控制器与视图之间的大部分连线都可以在Xcode中通过按住ctrl来连接。例如outlet,例如delegate。有了这些连线,他们之间的沟通算是畅通无阻了。
1)用户在view上的操作可以直接告诉控制器让控制器去响应
2)view需要的代理也可以指派给控制器让控制器去完成
3)view需要的数据源也需要控制器来提供
总之,控制器很忙,因为它非常被动。
控制器还需要一个角色的参与:model
顾名思义,模型。我觉得使用asp.net里mvc的domain来描述比较好理解,领域。例如你要开发一个图书管理系统,模型里描绘的就是图书的书名、售价、作者,谁借走了,几号借走的,一切关于这个应用领域的数据。
我们可以给模型一个简单的定义:它描述了一个应用所有需要抽象出来的数据结构和这些数据之间的关系,还有他们获取数据需要通过的途径(本地的、远程的)等。
有了模型,控制器想啥时候去拿数,想怎么拿都行。
仔细观察上面的图,有控制器到model的箭头,没有model到控制器的箭头。因为模型不需要知道控制器的存在,这样可以减少耦合,提高代码复用可能性。把你定义好的model挪到别的项目中,还可以使用。
但是问题来了,当model数据已经更新了,被修改了,怎么通知相关的控制器?注意model上方有个天线,高端!之所以使用无线的,是因为model不知道更改要发给谁,但是model可以广播,model的观点:谁关心我的更改让谁收听去,我对谁收听了我不感兴趣。
广播的方式有两种:Notification 和 KVO(都是设计模式,本系列接下来会详述)
好了,他们几个之间的关系基本有个概念了。mvc模式就是这样,把原本杂乱无章的类,分为三堆,严格监管,按规则行事。
还是那句话:
说到底一切都是为了使类之间的耦合性更松散。好的代码应该对扩展开放,对修改关闭。
此图解段转自 http://www.cnblogs.com/limlee --- GeekLion
Controller与Model之间的通信
Controller可以主动向Model发起会话
Model职能被动地回复Controller发起的会话,不能主动请求Controller
Controller与View之间的通信
Controller可以完全操控View,因为Controller要把View显示在屏幕上
View可以向Controller发送消息,因为View要将用户的动作传递给Controller
Model与View之间无法直接通信
总结:
Controller对Model——通过API
Controller对View ——通过Outlet
View对Controller ——Target-action,Delegate,Datasource
Model对Controller——Notification,KVO
View与Controller之间的通信方式
目标操作(target-action)
Controller内会悬挂一个目标(target),并将一个操作(action)给将要和它交流的视图对象,如图解中的target与action
如,为View中的某个按钮添加一个监听事件,当按钮被点击时就执行相应的处理
委托
为视图中的某个视图设置代理,当控件被操作时发送相应的代理消息,执行相应的代理 方法,实现View与Controller的通信
如,tableView的代理
数据源
Controller通过数据源将View需要的数据传递给View,实现Controller与View的通信