模型视图控制器(MVC)

Model-View-Controller(MVC)设计是一个与应用程序的全局体系结构有关的高层,并根据对象在应用程序中扮演的一般角色对对象进行分类。面向对象的程序通过适应MVC可以从多种方面受益他们设计的设计模式。 这些程序中的许多对象倾向于更可重用,并且它们的接口倾向于更好地定义。

它主要包括三层:

1)模型层

2)查看图层

3)控制器层

1)模型层:

模型层包含以下组件:

  • 网络代码 :此代码对于整个应用程序的网络通信非常有用
  • 持久性代码:此代码用于实现核心数据,或仅通过将NSData blob直接保存到磁盘即可。
  • 解析代码:解析网络响应之类的任何对象也应包括在模型层中。

模型对象封装了数据和基本行为,它们保存了应用程序的数据并定义了处理数据的逻辑。设计良好的MVC应用程序将其所有重要数据封装在模型对象中,任何数据都是应用程序持久状态的一部分一旦将数据加载到应用程序中,它应该驻留在模型对象中。

理想情况下,模型对象与用于呈现和编辑它的用户界面没有显式连接。 模型对象不应与界面和表示问题有关。

2)视图层:

当用户与您的应用进行交互时,他们正在与视图层进行交互。 视图不应该包含任何业务逻辑,因此被认为是应用程序的“哑巴”部分。 用代码术语,您通常会看到:

  • UIView子类:这些从基本的UIView到复杂的自定义UI控件。
  • UIViewController: UIViewController与自身的根UIView及其不同的周期(LoadView,ViewDidLoad)紧密耦合。
  • 动画和UIViewController过渡。
  • UIKIT / APPKIT,Core Animation和Core Graphics的一部分的类

检查视图图层时,请使用以下内容作为检查清单:

  • 它是否与模型层交互?
  • 它是否包含任何业务逻辑?
  • 它会尝试执行与UI不相关的任何操作吗?

如果我们很好地编写了这些类,则几乎可以随时重用它们。

视图对象向用户提供信息。视图对象知道如何显示并可能允许用户编辑应用程序模型中的数据。视图不应负责存储其显示的数据。视图对象可以位于负责仅显示模型对象的一部分,整个模型对象,甚至许多不同的模型对象。 视图有很多不同的种类。

视图对象倾向于可重用和可配置,并且它们在应用程序之间提供一致性。 在Cocoa中,AppKit框架定义了大量的视图对象,并在Interface Builder库中提供了许多视图对象。 通过重用AppKit的视图对象(例如NSButton对象),可以确保应用程序中的按钮的行为与其他任何Cocoa应用程序中的按钮一样,从而确保了应用程序之间外观和行为的高度一致性。

视图应确保其正确显示模型。 因此,通常需要了解模型的更改。 由于模型对象不应绑定到特定的视图对象,因此它们需要一种通用的方式来指示它们已更改。

3)控制器层:

控制器层是应用程序中最少可重用的部分,因为它涉及特定于域的规则。 控制器对象将模型绑定到视图。控制器对象充当应用程序的视图对象及其模型对象之间的中介。 控制器通常负责确保视图可以访问他们需要显示的模型对象,并充当视图了解模型更改的渠道。 控制器对象还可以为应用程序执行设置和协调任务,并管理其他对象的生命周期。

在典型的Cocoa MVC设计中,当用户通过视图对象输入值或指示选择时,该值或选择将传达给控制器对象。 控制器对象可能以某种特定于应用程序的方式解释用户输入,然后要么告诉模型对象如何处理此输入。

基于相同的用户输入,某些控制器对象还可能告诉视图对象更改其外观或行为的某个方面,例如告诉按钮禁用自身。 相反,当模型对象发生更改时(例如,访问新的数据源),模型对象通常会将更改传达给控制器对象,然后控制器对象请求一个或多个视图对象进行相应的更新。

MVC作为复合设计模式:

Model-View-Controller是一种设计模式,由多个其他基本设计模式组成。这些基本模式共同定义了MVC应用程序的功能隔离和通信路径。与可可分配的基本模式不同的一组基本模式。 区别主要在于赋予应用程序的控制器和视图对象的角色。

MVC由Composite,Strategy和Observer模式组成。

  • 组合:应用程序中的视图对象实际上是嵌套视图的组合,这些嵌套视图以协调的方式一起工作。 这些显示组件的范围从窗口到复合视图(例如表格视图)到单个视图(例如按钮)。 用户输入和显示可以在复合结构的任何级别进行
  • 策略 :控制器对象为一个或多个视图对象实现策略。 视图对象仅限于保持其视觉外观,并且将与接口行为的应用程序特定含义有关的所有决策委托给控制器。
  • 观察者:模型对象将感兴趣的对象(通常是视图对象)保留在应用程序中,告知其状态的更改。

用户在复合结构的某个级别上操纵视图,结果是生成了一个事件。 控制器对象接收事件并以特定于应用程序的方式解释该事件-即,它应用了策略。 该策略可以是请求模型对象更改其状态或请求视图对象(在复合结构的某个级别)以更改其行为或外观。 当状态改变时,模型对象又通知所有已注册为观察者的对象。 如果观察者是视图对象,则可以相应地更新其外观。

传统版本的MVC作为复合模式

MVC作为复合模式的可可版本与传统版本有一些相似之处,并且实际上很有可能构建一个可运行的应用程序。通过使用绑定技术,您可以轻松地创建其视图直接观察模型对象的Cocoa MVC应用程序接收状态更改的通知。 但是,这种设计存在理论上的问题。 视图对象和模型对象应该是应用程序中最可重用的对象。 视图对象表示操作系统和系统支持的应用程序的“外观”。 外观和行为的一致性至关重要,并且需要高度可重复使用的对象。 根据定义,模型对象封装与问题域关联的数据并对该数据执行操作。 在设计方面,最好使模型和视图对象彼此分开,因为这样可以增强其可重用性。

可可版本的MVC作为复合设计模式

这种复合设计模式中的控制器对象包含调解器模式和策略模式; 它在两个方向上介导了模型和视图对象之间的数据流。 通过应用程序的控制器对象传达模型状态的更改以查看对象。 另外,视图对象通过其对目标动作机制的实现来合并命令模式。

中介控制器从NSController的具体子类派生而来,这些类除了实现Mediator模式外,还提供了应用程序应利用的许多功能,例如选择和占位符值的管理。 而且,如果您选择不使用绑定技术,则您的视图对象可以使用诸如Cocoa通知中心之类的机制来接收来自模型对象的通知。 但这将需要您创建一个自定义视图子类,以添加有关模型对象发布的通知的知识。

作为nib文件的所有者的协调控制器。

在设计良好的Cocoa MVC应用程序中,协调控制器对象通常拥有中介控制器,这些控制器存储在nib文件中。

MVC应用程序的设计准则:

  • 尽管可以在一个对象中组合MVC角色,但是最好的总体策略是保持角色之间的分隔。 这种分离增强了对象的可重用性以及使用它们的程序的可扩展性。如果要合并一个类中的MVC角色,请为该类选择一个主要角色,然后在同一实现文件中使用类别来扩展对象。在课堂上扮演其他角色。
  • 设计良好的MVC应用程序的目标应该是使用尽可能多的可重用对象。 特别是,视图对象和模型对象应具有高度可重用性。 特定于应用程序的行为通常尽可能地集中在控制器对象中。
  • 尽管可以使视图直接观察模型以检测状态变化,但是最好不要这样做。 视图对象应始终通过中介控制器对象来了解模型对象中的更改。
  • 努力限制应用程序类中的代码依赖性。 一个类对另一个类的依赖性越大,可重用性就越差。 具体建议因所涉及的两个类别的MVC角色而异:
  • 视图类不应依赖于模型类(尽管某些自定义视图可能不可避免)。
  • 视图类不必依赖于中介控制器类。
  • 除其他模型类外,模型类不应依赖任何其他内容。
  • 中介控制器类不应依赖于模型类(尽管像视图一样,如果它是自定义控制器类,则可能是必需的)。
  • 中介控制器类不应依赖于视图类或协调控制器类。
  • 协调控制器类取决于所有MVC角色类型的类。

结论:

在MVC的帮助下,人们可以学习如何在应用程序中使用现代实践,并在结构性问题变得头痛之前预防它们。