【问题标题】:How to apply the MVC pattern to GUI development如何将 MVC 模式应用于 GUI 开发
【发布时间】:2008-10-07 07:11:43
【问题描述】:
我主要是一名 Web 开发人员,但我对 C++ 和 C# 有很好的了解。然而,最近我编写了一个 GUI 应用程序,我开始迷失如何处理控制器和视图逻辑之间的关系。在 PHP 中这很容易——我可以闭着眼睛写我自己的 MVC 模式——主要是因为 PHP 是无状态的,你可以根据请求重新生成整个表单。但是在应用程序编程语言中,我很快就会迷失方向。
我的问题是:如何将控制器与视图分开?视图应该附加到来自控制器的事件 - 还是应该实现控制器与之交互的接口?
【问题讨论】:
标签:
c#
c++
model-view-controller
user-interface
design-patterns
【解决方案1】:
如果我是你,我会从你的视图界面公开事件。这将允许您使控制器成为整个交互的中心。
控制器将首先加载并实例化视图,我将使用依赖注入,这样您就不会创建对视图本身的依赖,而只会在界面上创建依赖。
控制器将访问模型并将数据加载到视图中。
控制器将绑定到视图界面上定义的事件。
然后控制器将通过事件处理将数据保存回模型。
如果您愿意,您还可以使用事件代理,这样就无需为每个视图声明一个接口。这样您就可以通过属性绑定到事件。
这将使控制器依赖于模型和视图接口,视图仅依赖于数据而模型没有依赖关系。
以上设计思想的一些例子可以在CAB和智能客户端软件工厂Link To Smart Client中找到。他们使用 MVP 模式,但同样可以轻松地应用于 MVC 模式。
【解决方案2】:
大多数 GUI 框架(从 MFC 到 SWT 再到其他)都已经基于 MVC。事实上,MVC 模式最早是由 Smalltalk-80 创建的,后来才真正用于 GUI 开发。
仔细检查并查看您选择的 GUI 工具包的标准和建议做法。有时,在解决某个问题或使用特定工具包时,MVC 并不是一个很好的模式。
请记住:MVC 是一种很棒的模式,但并不是万能的解决方案,当基于事件或函数式编程会让您的生活更轻松时,不要试图将问题强加到 MVC 中。
【解决方案3】:
想象一下这个 GUI:
Zergling 单位作为外星人图标呈现给用户。您可以看到它处于空闲动画中。称之为视图。
玩家通过点击单位和目标位置来移动单位。如果需要,您可以将播放器替换为 AI。称它为控制器。
单位处于战斗状态时,每个游戏帧都会计算单位的生命值和攻击范围。您可以更改此数据以使 Zergling 成为一个范围单位。将此称为模型。
记住这个类比并将其扩展到您的 MVC 设计。
【解决方案4】:
您要记住的重要一点是,在您的 MVC 设置中,控制器必须知道要调用哪个视图,但视图必须对控制器一无所知。
因此,您的 View 必须为 Controller 与其交互提供一种通用的方式,以便您可以让多个不同的 Controller 调用同一个 View(例如,作为参数提供的某些数据的标准化图形输出)。
这为您提供了灵活性:
- 如果您的客户想要 PDF 输出
你只提供 HTML 的东西
输出,你可以逃脱
编写要调用的新 PDF 视图
从具有相同的控制器
参数作为 HTML 视图。
- 如果您的客户想要不同数据源的类似 HTML 输出(例如),您可以编写一个新控制器,该控制器为相同的旧 HTML 视图提供不同的数据集,从而提供与其他数据源相同的 HTML 报告数据。
如果您将 View 与特定的 Controller 分离,并了解从 Controller 调用哪个 View,那么您就顺利完成了。
【解决方案5】:
您的控制器应该明确地绑定到视图实现的接口上定义的事件。
如何执行此操作可能是棘手的部分。依赖注入?观景厂?视图是否实例化了它想要的控制器?这实际上取决于应用程序的复杂程度。
对于一些真正快速和简单的事情,我会先让每个视图都构造它的控制器,然后如果它需要变得更大,请查看其他选项。就我个人而言,我认为一个完整的依赖注入框架对于六种形式来说太过分了:]