Model-View-Controller
Model-View-Controller设计模式即MVC设计模式,也叫MVC框架模式。它的变体至少在Smalltalk的早期就已经存在了。它是一种高级模式,因为它关注应用程序的全局架构,并根据对象在应用程序中扮演的一般角色对它们进行分类。它也是一个复合模式,因为它包含几个更基本的模式。
面向对象程序通过采用MVC设计模式可以再在几个方面受益。面向对象程序中的许多对象趋向于更易于重用,它们的接口趋向于更好地定义。总的来说,这些程序更能适应不断变化的需求——换句话说,它们比不基于MVC的程序更容易扩展。此外,cocoac中的许多技术和架构——比如绑定、文档架构和可脚本性——都是基于MVC的,并且要求自定义对象扮演MVC定义的角色之一。
MVC对象的角色和关系
MVC设计模式认为有三种类型的对象:模型对象(Model,这里跟代码中的数据模型不是一个概念)、视图对象(View)和控制器对象(Controller)。MVC模式定义了这些类型的对象在应用程序及其通信线路中扮演的角色。在设计应用程序时,一个主要步骤是为属于这三组中的对象选择或创建自定义类。这三种类型的对象都通过抽象的边界与其他类型的对象分离,并跨越这些边界与其他类型的对象进行通信。
Model 对象封装数据和基本行为
Model对象代表特殊的知识和专长。它们保存应用程序的数据并定义操作该数据的逻辑。一个设计良好的MVC应用程序将所有重要的数据封装在Model对象中。一旦将数据加载到应用程序中,属于应用程序持久状态一部分的任何数据(无论该持久状态存储在文件或数据库中)都应该驻留在Model对象中。因为它们代表了与特定问题领域相关的知识和专业知识,所以它们往往是可重用的。
View对象将信息呈现给用户
View对象知道如何显示并允许用户编辑应用程序Model中的数据。View不应该负责存储它所显示的数据。(当然,这并不意味着View永远不会实际存储它正在显示的数据。出于性能原因,View可以缓存数据或执行类似的技巧)。View对象可以负责显示Model对象的一部分,或者整个Model对象,甚至是许多不同的Model对象。View有许多不同的种类。
View对象趋向于可重用和可配置,并且它们提供应用程序之间的一致性。在Cocoa中,AppKit框架定义了大量的View对象,并在Interface Builder库中提供了许多View对象。通过重用AppKit的View对象,比如NSButton对象,你可以保证应用程序中的按钮的行为就像任何其他Cocoa应用程序中的按钮一样,确保应用程序的外观和行为具有高度的一致性。
View应该确保它正确地显示Model。因此,它通常需要知道对Model的更改。因为Model对象不应该绑定到特定的View对象,所以它们需要一种通用的方式来指示它们已经更改。
Controller对象将Model绑定到View
Controller对象充当应用程序的View对象和Model对象之间的中介。Controller通常负责确保View能够访问它们需要显示的Model对象,并充当View了解模型更改的管道。Controller对象还可以执行应用程序的设置和协调任务,并管理其他对象的生命周期。
在典型的Cocoa MVC设计中,当用户通过View输入一个值或指示一个选择时,该值或选择将被传递给Controller对象。Controller对象将会解释用户一些特定于应用程序输入的方式,然后会告诉一个Model对象,如何处理这个输入的例子中,“添加一个新值”或“删除当前记录”——或者它可以使Model对象反映出它的一个属性的变化。基于相同的用户输入,一些Controller对象可能还会告诉View对象更改其外观或行为的一个方面,例如告诉按钮禁用自己。相反,当Model对象发生变化时(例如,访问了一个新的数据源),Model对象通常将该变化传递给Controller对象,然后Controller对象告诉一个或多个View对象相应地更新它们自己。
Controller对象可以是可重用的,也可以是不可重用的,这取决于它们的一般类型。
合并角色
可以合并一个对象所扮演的MVC角色,例如,使一个对象同时满足Controller和View的角色——在这种情况下,它将被称为ViewController。以同样的方式,您还可以拥有Model-Controller对象。对于某些应用程序来说,像这样组合角色是可以接受的设计。
ModelController是一个主要关注Model层的Controller。它“拥有”Model;它的主要职责是管理Model和与View对象通信。应用于整个Model的操作方法通常在ModelController中实现。文档体系结构为您提供了许多这样的方法;例如,NSDocument对象(它是文档体系结构的核心部分)自动处理与保存文件相关的操作方法。
ViewController是一个主要关注View层的Controller。它“拥有”接口(View);它的主要职责是管理接口和与Model通信。与View中显示的数据相关的操作方法通常在ViewController中实现。NSWindowController对象(也是文档架构的一部分)是视图控制器的一个例子。
MVC应用程序的设计指南提供了一些关于合并MVC角色的对象的设计建议。
Cocoa控制器对象的类型
Controller对象将Model绑定到View勾勒出了Controller对象的抽象轮廓,但实际情况要复杂得多。在Cocoa中有两种一般的Controller对象:中介控制器(mediating controllers)和协调控制器(coordinating controllers)。每种控制器对象都与一组不同的类相关联,每种类都提供不同范围的行为。
中介控制器通常是继承自NSController类的对象。在Cocoa绑定技术中使用中介控制器对象。它们促进(或中介)View对象和Model对象之间的数据流。
备注:AppKit实现了NSController类及其子类。这些类和绑定技术在iOS中不可用。
MVC是一个复合设计模式
Model-View-Controller是一种由几个更基本的设计模式组成的设计模式。这些基本模式共同定义了功能分离和通信路径,这是MVC应用程序的特征。然而,传统的MVC概念分配的一组基本模式与Cocoa分配的不同。区别主要在于应用程序的Controller和View的角色。
传统的MVC
在最初的概念(Smalltalk)中,MVC由Composite(组合)、Strategy(策略)和Observer(观察者)模式组成。
- Composite——应用程序中的View对象实际上是以协调方式(即视图层次结构)一起工作的嵌套视图的组合。这些显示组件范围从窗口到复合视图(如表视图),再到单个视图(如按钮)。用户输入和显示可以发生在复合结构的任何级别。
- Strategy——一个Controller对象为一个或多个View对象实现策略。View将自己限制在维护其可视化方面,并将所有关于接口行为的应用程序的特定含义的决议委托给控制器。
- Observer ——模型对象保持应用程序中感兴趣的对象(通常是视图对象),并通知其状态的变化。
Composite、Strategy和Observer模式一起工作的传统方式如图1所示:用户在复合结构的某个层次上操作一个视图,结果生成一个事件。Controller对象接收事件并以特定于应用程序的方式解释它——也就是说,它应用一个策略。这个策略可以是请求(通过消息)Model对象更改其状态,或者请求View对象(在复合结构的某个级别上)更改其行为或外观。反过来,当Model对象的状态发生变化时,它会通知所有已注册为观察者的对象;如果观察者是一个View对象,它可能会相应地更新它的外观。
图1——传统MVC.jpg
Cocoa 版本MVC
Cocoa版本的MVC是一种复合模式,与传统的MVC有一些相似之处,实际上可以根据图1构建一个工作的应用程序。通过使用绑定技术,您可以轻松地创建一个Cocoa MVC应用程序,该应用程序的View可以直接观察Model对象,以接收状态更改的通知。然而,这种设计存在一个理论问题。View对象和Model对象应该是应用程序中最可重用的对象。View对象表示操作系统和系统支持的应用程序的“外观和感觉”;外观和行为的一致性是必不可少的,这需要高度可重用的对象。模型对象通过定义封装与问题域关联的数据,并对该数据执行操作。在设计方面,最好保持View和Model对象彼此分离,因为这可以增强它们的可重用性。
在大多数Cocoa应用程序中,Model对象的状态变化通知通过Controller对象传达给View对象。图2显示了这种不同的配置,尽管涉及了两个更基本的设计模式,但它看起来更加清晰。
图2——Cocoa的MVC.jpg
这种复合设计模式中的Controller对象结合了中介模式和策略模式;它调解Model和View对象之间双向的数据流。Model状态的变化通过应用程序的Controller对象传达给View对象。此外,View对象通过target-action机制的实现合并了Command(命令)模式。
注意:target-action机制允许View对象通信用户输入和选择,它可以在协调控制器对象和中介控制器对象中实现。然而,每个控制器类型的机构设计是不同的。为了协调控制器,你在Interface Builder中将View对象连接到它的目标(Controller对象),并指定一个动作选择器,该动作选择器必须符合特定的签名。协调控制器,由于是窗口和全局应用程序对象的委托,也可以在响应器链中。中介控制器使用的绑定机制将View对象连接到target,并允许带有任意类型的可变数量参数的action签名。然而,中介控制器不在响应器链中。
网友评论