美文网首页
苹果眼中的MVC

苹果眼中的MVC

作者: 行知路 | 来源:发表于2020-04-29 14:43 被阅读0次

        基于苹果提供的库进行开发的同学应该都听说过MVC这种设计模式,也都实际中使用过这种模式,但是每个人对MVC的理解是不同的,按照自己的理解实现的MVC更是不同的。大家应该很想知道在苹果的眼中,他们所定义的MVC到底是什么样子的,以下文章翻译自苹果官方文档,让我们看看苹果对MVC的认知。

一、Model-View-Controller

        Model-View-Controller(MVC)这种设计模式具有悠久的历史。自Smalltalk诞生以来它就一直在演变(MVC的概念最早来自Smalltalk)。它是一种高阶的设计模式,主要考虑应用程序的全局架构,并根据对象在应用程序中所扮演的角色对其进行分类(划分为Model、View、Controller)。它是一个包含多种基本模式的复合模式。
        面向对象程序开发通过使用MVC模式可以获得多样的收益。这样的程序中的对象能够更好的被定义、重用。这些程序总体上更适应不断变化的需求——换句话说,与不基于MVC的程序相比,它们更容易扩展。此外,Cocoa中的许多技术和体系结构(例如绑定、文档体系结构等)都基于MVC,并且要求自定义对象能够扮演MVC中的某个角色。

二、MVC对象的角色与关系

        MVC设计模式认为存在三种类型的对象:模型对象,视图对象和控制器对象。MVC模式定义了这些类型的对象在应用程序中扮演的角色及其通信线路。 在设计应用程序时,主要步骤是选择或创建属于这三个组之一的对象。三种类型的对象中的每一种都通过抽象边界与其他类型的对象分开,并跨这些边界与其他类型的对象进行通信。

2.1 Model对象封装数据与基本行为

        模型对象代表特殊的知识和专长。他们保存应用程序的数据并定义处理该数据的逻辑。设计良好的MVC应用程序将其所有重要数据封装在模型对象中。一旦将数据加载到应用程序中,任何属于应用程序持久状态的数据(无论该持久状态存储在文件还是数据库中)都应驻留在模型对象中。因为它们代表与特定问题领域相关的知识和专长,所以它们具有可重用的特性。
        理想情况下,模型对象与用于呈现和编辑它的用户界面没有显式连接。例如,如果您有一个代表人的模型对象(例如您正在写通讯录),则可能要存储生日。将其存储在您的Person模型对象中是一件好事。但是,日期格式字符串或其他有关该日期显示方式的信息则存储在别处,更好一些。
        实际上,这种分离并不总是最好的,这里有一定的灵活性空间,但是通常,模型对象不应与接口和表示问题有关。一个合理的例外情况是一个绘图应用程序,该应用程序具有代表所显示图形的模型对象。图形对象知道如何绘制自己是有意义的,因为它们存在的主要原因是定义视觉对象。但是即使在这种情况下,图形对象也不应依赖于存在于特定视图或任何视图中,并且它们也不应该负责知道何时绘制自己。 应该要求它们通过要呈现它们的视图对象进行绘制。
        对于本段的所说的理论本人是赞同的,但是对于所举示例,本人则不赞同。在此示例中,更应该是由View对象来承担如何绘制的职责。在讲述设计模式、面向对象(讲继承的时候)等相关书籍、文章中,此示例经常被提及。

2.2 View对象向用户展示信息

        视图对象知道如何显示,并且可能允许用户编辑应用程序模型中的数据。 该视图不应负责存储其显示的数据。(当然,这并不意味着视图从不实际存储其显示的数据。出于性能原因,视图可以缓存数据或执行类似的操作)。 视图对象可以负责仅显示模型对象的一部分、整个模型对象甚至许多不同的模型对象。视图有很多不同的种类。
        视图对象倾向于可重用和可配置,并且它们在应用程序之间能够表现出一致性。在Cocoa中,AppKit框架定义了许多视图对象,并在Interface Builder库中提供了许多视图对象。通过重用AppKit的视图对象(例如NSButton对象),可以确保应用程序中的按钮的行为与其他任何Cocoa应用程序中的按钮一样,从而确保了各个应用程序在外观和行为上的高度一致性。
        视图应确保其正确显示模型。 因此,它通常需要了解模型对象发生了更改。由于模型对象不应绑定到特定的视图对象,因此它们需要一种通用的方式来通知它们已更改。

2.3 控制器对象把模型绑定到视图

        控制器对象充当应用程序的视图对象与其模型对象之间的中介。控制器通常负责确保视图可以访问他们需要显示的模型对象,并充当视图了解模型更改的渠道。控制器对象还可以为应用程序执行设置和协调任务,并管理其他对象的生命周期。

        在典型的Cocoa MVC设计中,当用户输入值或通过视图对象改变选择时,该值或选择将传达给控制器对象。控制器对象可能以某种特定于应用程序的方式解释用户输入,然后要么告诉模型对象如何处理此输入(例如,“添加新值”或“删除当前记录”)。

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

        控制器对象可以是可重用的也可以是不可重用的,这取决于它的类型。控制器类型小节讲述了cocoa中不同的控制器对象。

2.4 组合角色

        在MVC中,一个对象和合并其他对象的职责,例如,把控制器对象与视图对象的职责合并到一起,称之为ViewController。同样,也可以有一个ModelController对象。对于一些应用程序,组合角色是可以接受的设计

        模型控制器是主要与模型层有关的控制器。它“拥有”模型;它的主要职责是管理模型并与视图对象进行通信。适用于整个模型的动作方法通常在模型控制器中实现。文档体系结构为您提供了许多这些方法。例如,一个NSDocument对象(它是文档体系结构的中心部分)自动处理与保存文件有关的操作方法。

        视图控制器是主要与视图层相关的控制器。它“拥有”界面(视图);它的主要职责是管理界面并与模型进行通信。与视图中显示的数据有关的动作方法通常在视图控制器中实现。NSWindowController对象(也是文档体系结构的一部分)是视图控制器的示例。

三、Cocoa控制器类型

        控制器对象把模型绑定到视图概述了控制器对象的抽象概念。但实际上,情况要复杂得多。 在Cocoa中,有两种通用的控制器对象:中介控制器和协调控制器。每种控制器对象都与一组不同的类相关联,并且每种提供不同的行为范围。

        中介控制器通常是从NSController类继承的对象。中介控制器对象用于Cocoa绑定技术中。它们促进或调解了视图对象和模型对象之间的数据流。

在iOS中,不可使用此类型的控制器对象。

        中介控制器通常是您从Interface Builder库中拖动的现成对象。您可以配置这些对象,以在视图对象的属性和控制器对象的属性之间,然后在那些控制器属性和模型对象的特定属性之间建立绑定。结果,当用户更改在视图对象中显示的值时,新值将自动通过中介控制器传递给模型对象进行存储。 当模型的属性更改其值时,该更改将传达给视图以进行显示。抽象的NSController类及其具体子类(NSObjectController,NSArrayController,NSUserDefaultsController和NSTreeController)提供了支持功能,例如提交和放弃更改的能力以及对选择和占位符值的管理。

        协调控制器通常是NSWindowController或NSDocumentController对象(仅在AppKit中可用),或者是NSObject的自定义子类的实例。 它在应用程序中的作用是监视或协调整个应用程序或部分应用程序的功能,例如从nib文件中未归档的对象。 协调控制器提供以下服务:

  • 响应委托消息并观察通知
  • 响应动作消息
  • 管理拥有对象的生命周期(例如,在适当的时间释放它们)
  • 在对象之间建立连接并执行其他设置任务

        NSWindowController和NSDocumentController是基于文档的应用程序的Cocoa体系结构的一部分。这些类的实例为上面列出的几种服务提供了默认实现,您可以创建它们的子类来实现更多特定于应用程序的行为。您甚至可以使用NSWindowController对象来管理不基于文档体系结构的应用程序中的窗口。

        协调控制器通常拥有归档在nib文件中的对象。作为文件的所有者,协调控制器位于nib文件中的对象外部,并管理这些对象。这些拥有的对象包括中介控制器以及窗口对象和视图对象。有关将控制器协调为文件所有者的更多信息,请参见MVC作为复合设计模式。

        自定义NSObject子类的实例可以完全适合用作协调控制器。这些类型的控制器对象结合了中介功能和协调功能。对于中介行为,他们利用诸如目标动作,出口,委托和通知之类的机制来促进数据在视图对象和模型对象之间的移动。它们往往包含许多粘合代码,并且由于该代码专门针对特定应用程序,因此它们是应用程序中最少可重用的对象。

四、作为复合模式的MVC

        Model-View-Controller是一种设计模式,由多个其他基本设计模式组成。这些基本模式共同定义MVC应用程序所特有的功能和通信路径。但是,MVC的传统概念与Cocoa的不同在于——Cocoa赋予控制器和视图对象的角色不同。

        在Smalltalk中,MVC由策略、组合、观察者模式组合而成。

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

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

传统MVC

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

        在大多数Cocoa应用程序中,模型对象中状态更改的通知通过控制器对象传递给查看对象。下图显示了这种不同的配置,尽管涉及了两个以上的基本设计模式,但看起来更清晰。

CocoaMVC

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

目标动作机制使视图对象能够传达用户输入和选择,可以在协调和中介控制器对象中实现。但是,每种控制器类型的机制设计都不同。 对于协调控制器,可以在Interface Builder中将视图对象连接到其目标(控制器对象),并指定必须符合特定签名的操作选择器。由于是窗口和全局应用程序对象的委托,因此协调控制器也可以位于响应者链中。中介控制器使用的绑定机制还将视图对象连接到目标,并允许使用可变数量的任意类型的参数进行动作签名。 但是,中介控制器不在响应者链中。

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

        在设计良好的Cocoa MVC应用程序中,协调控制器对象通常拥有中介控制器,这些控制器存储在nib文件中。 下图显示了两种类型的控制器对象之间的关系。

中介控控制器与协调者控制器

五、MVC应用程序设计指南

        以下准则适用于基于模型-视图-控制器的应用程序设计:

  • 尽管您可以使用NSObject的自定义子类的实例作为中介控制器,但是不应该只是用一个控制器完成所有的工作。而是使用为Cocoa绑定技术设计的现成的NSController对象——也就是说,使用NSObjectController,NSArrayController,NSUserDefaultsController或NSTreeController的实例,或者使用这些具体NSController子类之一的自定义子类。但是,如果应用程序非常简单,并且更愿意编写使用outlet和target-action实现中介行为所需的粘合代码,则可以随意使用自定义NSObject子类的实例作为中介控制器。在自定义NSObject子类中,还可以使用键值编码,键值观察和编辑器协议来实现NSController意义上的中介控制器。
  • 尽管可以将MVC角色组合在一个对象中,但是最佳的总体策略是保持角色之间的分隔。这种分离提高了对象的可重用性以及使用它们的程序的可扩展性。如果要合并一个类中的MVC角色,请为该类选择一个主要角色,然后(出于维护目的)在同一类中使用类别 实现文件扩展类,以扮演其他角色。
  • 设计良好的MVC应用程序的目标应该是使用(理论上至少)可重用的尽可能多的对象。特别是,视图对象和模型对象应具有高度可重用性。(当然,现成的中介控制器对象是可重用的。)特定于应用程序的行为通常尽可能地集中在控制器对象中。
  • 尽管可以让视图直接观察模型以检测状态变化,但是最好不要这样做。视图对象应始终通过中介控制器对象来了解模型对象中的更改。 原因有两个:
    • 如果使用绑定机制使视图对象直接观察模型对象的属性,则会绕过NSController及其子类为应用程序提供的所有优势:选择和占位符管理以及提交和放弃更改的能力。
    • 如果不使用绑定机制,则必须对现有视图类进行子类化,以增加观察模型对象发布的更改通知的能力。
  • 努力限制应用程序类中的代码依赖性。一个类对另一个类的依赖性越大,可重用性就越差。具体建议因所涉及的两个类别的MVC角色而异
    • 视图类不应依赖于模型类(尽管某些自定义视图可能无法避免)。
    • 视图类不营依赖于中介控制器类
    • 除其他模型类外,模型类不应依赖任何其他内容。
    • 中介控制器类不应依赖于模型类(尽管像视图一样,如果它是自定义控制器类,则可能有必要)。
    • 中介控制器类不应依赖于视图类或协调控制器类。
    • 协调控制器类取决于所有MVC角色类型的类。
  • 如果Cocoa提供了解决编程问题的体系结构,并且该体系结构将MVC角色分配给特定类型的对象,请使用该体系结构。 如果这样做,将项目组合在一起会容易得多。例如,文档体系结构包括一个Xcode项目模板,该模板将NSDocument对象(每个nib模型控制器)配置为文件的所有者。

六、Model-View-Controller in Cocoa (OS X)

模型-视图-控制器设计模式是许多Cocoa机制和技术的基础。因此,在面向对象的设计中使用MVC的重要性不仅限于为自己的应用程序获得更大的可重用性和可扩展性。如果您的应用程序要结合基于MVC的Cocoa技术,那么,如果其设计也遵循MVC模式,则你的应用程序将运行最佳。如果你的应用程序具有良好的MVC分隔,那么使用这些技术应该相对容易一些,但是如果你没有很好的分隔,那么使用这种技术将花费更多的精力。

OS X中的Cocoa包含以下基于模型-视图-控制器的体系结构,机制和技术:

  • 文档架构。 在此体系结构中,基于文档的应用程序由整个应用程序的控制器对象(NSDocumentController),每个文档窗口的控制器对象(NSWindowController)和将每个文档的控制器和模型角色组合在一起的对象(NSDocument)组成。
  • 绑定。 MVC是Cocoa绑定技术的核心。抽象NSController的具体子类提供了现成的控制器对象,你可以将其配置为在视图对象和设计正确的模型对象之间建立绑定。
  • 应用程序脚本化。 在设计应用程序使其可编写脚本时,不仅必须遵循MVC设计模式,而且还必须正确设计应用程序的模型对象。 访问应用程序状态并请求应用程序行为的脚本命令通常应发送到模型对象或控制器对象。
  • 核心数据。 核心数据框架管理模型对象的图,并通过将对象保存到持久性存储(并从持久性存储中检索它们)来确保持久性。 核心数据与Cocoa绑定技术紧密集成。 MVC和对象建模设计模式是Core Data体系结构的重要决定因素。
  • 撤消。 在撤消体系结构中,模型对象再次扮演核心角色。模型对象的原始方法(通常是其访问器方法)通常用于实现撤消和重做操作。 动作的视图和控制器对象也可能涉及这些操作。例如,您可能使此类对象为撤消和重做菜单项指定了特定的标题,或者使您在文本视图中使撤消选择成为可能。

相关文章

  • 苹果眼中的MVC

    基于苹果提供的库进行开发的同学应该都听说过MVC这种设计模式,也都实际中使用过这种模式,但是每个人对MVC的理解是...

  • MVC模式解析

    一、引子 在苹果眼中的MVC[https://www.jianshu.com/p/39a97e25d467]文章中...

  • 关于MVC MVP MVVM架构模式的总结

    一、MVC 首先关于MVC:MVC是苹果官方推荐的模式结构,MVC即 Model View Controller,...

  • iOS中常用的一些架构模式:

    MVC[https://zh.wikipedia.org/wiki/MVC] 苹果典型的MVC模式,用户通过 Vi...

  • iOS项目架构

    一、架构分层二、UI层架构 1、MVC  1.1 苹果版MVC  1.2 变种MVC 2、MVP 3、MVVM 一...

  • iOS - MVC、MVP、MVVM

    一、MVC MVC 模式,即 Model-View-Controller。它是苹果公司官方推荐的 App 开发架构...

  • iOS 设计模式 浅析MVC、MVP、MVVM

    一、MVC (Model、View、Controller) 苹果官方推荐的架构模式(MVC),最核心的就是通过Co...

  • iOS MVC、MVP、MVVM

    MVC模式 MVC模式,即Model-View-Controller。它是苹果公司官方推荐的 App 开发架构,也...

  • iOS开发之MVVM+RAC架构模式

    在说MVVM之前,首先要了解我们最常用的MVC设计模式⬇️ 1.MVC设计模式 苹果官方将MVC设计模式作为iOS...

  • 常见的客户端架构解析

    一千个程序员眼中有一千种 MVC SmallTalk MVC Models Models 表示知识。 一个 Mod...

网友评论

      本文标题:苹果眼中的MVC

      本文链接:https://www.haomeiwen.com/subject/mtogwhtx.html