6

谁能举一个例子说明为什么使用 MVC 而不是更简单的模型和视图是有利的。

注意:不管是 MVC 还是 MVP(Model-View-Presenter),我说的是 View 接收输入,然后 Controller 会通过将输入解释成一些动作来响应输入事件由模型。当模型发生变化时,视图将通过响应来自模型的事件来更新自身。

简单地让模型响应视图中的事件有什么缺点,反之亦然?

在 MVC 中,如果我以影响控制器的方式更改模型,那么我将不得不在控制器中进行更改。在模型视图中,如果我更改模型,我将不得不更新视图。

那么,似乎我们通过添加“控制器”部分来引入复杂性?

4

3 回答 3

4

在 MVC 中,模型对其环境视而不见,视图也可以——将其事件(盲目地)传递给控制器​​,控制器对视图和模型了解更多。因此,总而言之,控制器是系统的“不可重复使用”的一次性部分,因为它是最能感知上下文的组件。

如果我以影响控制器的方式更改模型...

模型应该以这样一种方式公开简单的 CRUD 方法,即那些使用这些方法的人不必知道有关传递的更新对象的任何信息,也不必知道模型内部到底发生了什么。

这意味着视图,IMO,必须通过创建传递的记录来做一些工作,因为控制器应该是无状态的并且视图更持久。控制器被触发并“启动”使用传递的对象进行工作并且没有状态。

传递的数据是由某种通用约定创建的。

让我走得更远。假设您有一个视图、一个表格网格,并且在网格中选择了一个其启用属性依赖于项目的控件——您可以创建一个在内部处理这些控件和此逻辑的视图,这可能是要走的路在这样一个简化的例子中。

但是您的视图越原子,它们就越可重用,因此您为每个,是的,每个控件创建一个视图。现在,您正在考虑一种情况,即视图必须相互了解才能注册自己以获得正确的通知......

这就是控制器介入的地方,因为我们想将所有这些依赖项都粘在他身上,这是长期一次性的。所以控制器管理这种类型的视图到视图通知方案。

现在你的观点是无知的,因为它们可以是独立的,因此是可重用的。

您可以编写视图,而无需了解系统或他们喜欢称之为“业务逻辑”的信息。您可以编写模型而不必对您的目标有太多了解(尽管它确实有助于调整模型以使其能够返回您想到的数据集)....但是控制器,它们是最后的,您必须拥有在你把东西连接在一起之前,前两个已经确定了。

这是需要考虑的另一件事——就像模型应该抽象出来并为其管理的数据的底层实现提供通用接口一样(客户端不知道数据是否来自数据库、文件,程序设置等)——视图还应该抽象出它正在使用的控件。

所以,最终这意味着视图不应该(下面的警告)具有如下所示的功能/属性:

public property BackgroundColor{get;set}

也不

public function ScrollBy(x,y){}

但反而:

public SetProp(string name, object val){}

public DoCmd(string name, object val){}

这有点做作,记住我最终说过......你问为什么这是个好主意?

考虑到可重用性,考虑到有一天您可能希望将某些东西从 WinForms 移植到 Flex,或者只是想使用可能不会公开相同功能的新型控件库。

我在这里说“移植”,但这真的不是目标,我们不关心移植这个特定的应用程序,而是让底层的 MVC 元素足够通用,可以被带到一个新的风格——在内部,留下一个一致的和能力- 独立的外部接口完好无损。

如果您不这样做,那么当您的新风格出现时,您对(可能可重用/可重构/可扩展的)控制器中的视图属性的所有硬引用都必须被弄乱。

这并不意味着此类通用设置器和 cmds 必须是您所有视图功能的接口,而是它们应该处理“边缘情况”属性以及您可以以传统硬链接方式公开的普通 props/cmds . 将其视为“扩展属性”处理程序。

这样,(再次设计),假设您正在构建一个按钮不再具有 buttonIcon 属性的框架。这很酷,因为您有远见地创建了一个按钮视图界面,​​其中 buttonIcon 是一个扩展属性,并且在视图内部,您的条件代码现在在收到 set/get 时执行无操作。

总之,我想说 MVC 的编码目标应该是为它们的底层组件提供 Model 和 View 通用接口,所以当你编写 Controller 时,你不必认真考虑你在控制谁. 虽然控制器被(似乎不公平地)设置为长期可重用性的牺牲品 - 这并不意味着您的所有控制器都注定要死亡。

他们希望很小,因为他们的许多“思考”已经被推到半智能模型和视图以及其他控制器中(例如:对网格进行排序或操作 TreeView 的控制器)——所以它们很小很容易被查看并且有资格在您的下一个项目中重用 - 或者克隆和调整以变得合适。

于 2012-01-14T18:59:29.800 回答
1

它实际上通过将工作流逻辑与域逻辑分离来降低复杂性。它还使编写单元测试变得更容易,并使您的应用程序更易于维护和扩展。

想象一下,如果你想添加一个新的数据类型。使用上述方法,您可能会在新类中复制大量工作流逻辑,因为它可能与域逻辑紧密耦合。

将工作流逻辑分离到控制器中所涉及的规则使您更有可能在工作流和域逻辑之间拥有更少的依赖关系。添加新的数据类型会更简单,您创建新的域对象并查看可以重用多少控制器,例如通过从控制器超类继承。

它还将使将来更改框架变得更容易-该模型可能不会更改太多,因此更便携。

话虽如此,您可能希望根据您用作表示层的内容来研究 MVVM:MVVM 优于 MVC 的好处

于 2012-01-14T18:01:12.740 回答
1

MVC/P(我在这里说的是监督控制器)相对于 MV 的优点包括:

  • 如果需要,您可以在控制器中处理复杂的数据绑定代码。

  • 您可以在没有 UI 测试框架的情况下测试复杂的表示逻辑。

  • 您还可以让图形设计师制作您的视图,而不是看到您的代码,并且在他们修复您的视图时不会弄乱您的代码。

于 2012-05-19T07:09:01.510 回答