在 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 的控制器)——所以它们很小很容易被查看并且有资格在您的下一个项目中重用 - 或者克隆和调整以变得合适。