4

我在 PHP 中使用 MVC。我没有使用框架,我只是想了解这种模式。

有时我会看到控制器,例如在本教程中,使用传递给构造函数的模型和视图进行实例化,而在同一个教程中,视图(此处为“模板”)类在构造函数中采用了控制器!

所以我的问题是:

  1. 为什么视图可能需要对其控制器的引用?视图不应该是这种关系中的被动伙伴吗?
  2. 控制器是否应该有对特定模型的内部引用?或者换一种说法,为什么不在控制器动作中实例化模型并以这种方式使用它们呢?
4

5 回答 5

9

鉴于网络上 MVC 的许多变化和误解,我投票以“不具建设性”来结束这个问题。由于评论数量有限,我将这个答案作为社区 Wiki 提供。

在此处输入图像描述

MVC 最初是由 Trygve Reenskaug 为桌面环境而不是为 Web 构想的。我们现在看到的大多是原始模式的某种形式的变体,如 MVP、HMVC、Model2-MVC 等。它们的实现彼此不同,人们花了很多时间争论“MVC”到底是什么或应该如何实现。

在此处输入图像描述

就个人而言,我更喜欢MVC 的企业应用架构模式定义,它说 MVC将用户界面交互分为三个不同的角色,因为这个定义没有实现的概念。

在书中,Fowler 指出,最重要的区别是模型与控制器和视图的分离。虽然这本书确实涵盖了角色之间的关联以使该论点得到理解,但我认为重点是理解和关注角色而不是实现。

设计模式是蓝图,而不是详细的示意图。此外,MVC 是一种模式语言。它的目的是为项目添加结构/形式。了解角色的用途,然后提出适用于您项目的实施。

在此处输入图像描述

Fowler 还有一篇关于 GUI 架构的长篇文章,涵盖 MVC,详细解释了关联和依赖关系,以防您手头没有这本书。

图片/幻灯片来自:失落的建筑(罗伯特·塞西尔·马丁;2011 年 11 月 4 日)

于 2012-06-14T09:42:24.960 回答
3
  1. 如果您有用户输入,您需要知道将它们发送到哪里......到哪个控制器。

  2. 我不喜欢让我的控制器直接玩模型,因为控制器暴露在“外部世界”中,并且容易受到攻击。您可以查看服务层模式、数据传输对象模式等。我喜欢将我的模型隔离在控制器将使用的服务 API 后面。如果您需要一本关于模式的好书,可以查找 Martin Fowler 的 :)

于 2012-06-14T09:00:05.360 回答
1
  1. 视图不应该引用控制器(当然动作链接除外)。控制器执行它被告知的操作并将结果发送到视图。

  2. 就我使用 MVC 而言,我在动作中实例化模型并以这种方式使用它。我不喜欢将控制器绑定到模型。通常我使用存储库结构来访问我的模型。在较大的项目中,我在控制器和模型之间有一个服务层。在 .net MVC 中,我开始使用视图模型作为应用程序的控制器和 MVC 部分查看的实体,而我的服务处理与我的域模型有关的任何事情并返回视图模型。

于 2012-06-14T09:14:15.970 回答
1

由于我已经设法在 MVC 和 PHP 的上下文中广泛地编写模型,让我们只关注ViewController部分的三元组。

正如@Gordon已经提到的那样,我们在 Web 中所做的不是经典的 MVC。这是不可能的集会。相反,我们在原始想法上提出了不同的变化。

视图不是模板

除非您使用的 MVP 实现特别糟糕,否则view实例都是对象,负责表示逻辑。

实例是否controller需要访问view取决于您使用的受 MVC 启发的模式。在 MVP 和 MVVM 模式中,controller实例请求信息model layer并将其传递给view(通过一些修改或附加标志)。

在 Model2 模式(更接近原始概念)中,view实例本身能够从model layer. 在这种情况下,例如不需要controller访问它。

控制器负责什么?

的实例controller不应直接从model layer. 有两个主要原因:

  • 导致与特定类名的紧密耦合,使测试和维护更加困难
  • 增加了额外的责任(或改变的理由),因此 - 违反了SRP

结构的初始化model layer很复杂。它们通常要求您从model layer. 此任务应留给控制器使用的单独的类似工厂的实例(在实例之间共享)controllerview

实例的主要职责controller应该是改变model layer. 它应该接受用户的输入,并将其翻译成可以理解的形式model layer

请记住,model layer作为一个整体,必须完全不了解view实例controller

于 2012-06-14T10:12:04.527 回答
1

根据我的经验,对于 MVC 的确切含义有很多解释。几乎每个人都普遍同意:

  • 模型实现业务逻辑,并封装数据访问。
  • 视图实现表示逻辑。
  • 控制器处理输入和控制流。

他们如何相互联系和交谈是辩论、争论、格斗和圣战的问题。

在实践中,控制器通常会加载视图和模型,视图有时会加载模型和控制器,但模型通常不会加载控制器或视图。

为什么视图会加载控制器?假设您实现了一个拥有自己的控制器、模型和视图的小部件。您想在多个位置的多个页面上加载此小部件。最简单的方法是在视图中加载小部件的控制器。

为什么视图会加载模型?也许您编写了控制器,以便它可以加载两个或更多视图,并且您不想为每个非常不同的视图加载不同的模型。所以你只需告诉每个视图加载它自己的模型。

分离角色,但允许任何最有效和最合乎逻辑地实现您需要的系统的交互。

于 2012-06-14T14:11:26.753 回答