我主要是一名web开发人员,但我对C++和C#有很好的理解。然而,最近我写了一个GUI应用程序,我开始迷失在如何处理控制器和视图逻辑之间的关系上。在PHP中,这非常容易——我可以闭着眼睛编写自己的MVC模式——主要是因为PHP是无状态的,并且可以根据请求重新生成整个表单。但在应用程序编程语言中,我很快就会迷失方向。
我的问题是:如何将我的控制器与视图分离?视图应该连接到来自控制器的事件,还是应该实现控制器与之交互的接口?
如果我是你,我会从你视图的接口中公开事件。这将允许您使控制器成为整个交互的中心。
控制器将首先加载并实例化视图,我将使用依赖项注入,这样您就不会在视图本身上创建依赖项,而只会在接口上创建。控制器将访问模型并将数据加载到视图中。控制器将绑定到视图接口上定义的事件。然后,控制器将处理通过事件将数据保存回模型。
如果你愿意,你也可以使用一个事件代理,这样就不需要为每个视图声明一个接口了。通过这种方式,您可以通过属性绑定到事件。
这将使控制器依赖于模型和视图接口,视图仅依赖于数据,而模型没有依赖关系。
上述设计思想的一些例子可以在CAB和智能客户端软件工厂链接到智能客户端中找到。他们使用MVP模式,但它同样可以很容易地应用于MVC模式。
大多数GUI框架(从MFC到SWT,再到任何东西)都已经是基于MVC的。事实上,MVC模式最早是由Smalltalk-80创建的,后来第一次真正用于GUI开发。
仔细检查并查看所选GUI工具包的标准和建议做法。在解决某个问题或使用某个特定工具包时,MVC有时不是一个好的模式。
记住:MVC是一个很好的模式,但不是一个一刀切的解决方案,当基于事件或函数式编程会让你的生活更轻松时,不要试图把问题强加给MVC。
想象一下这个GUI:
Zerling单元以外星人图标的形式呈现给用户。您可以看到它处于空闲动画中。称之为"视图"。
玩家通过点击单位和目标位置来移动单位。如果你愿意的话,你可以把玩家换成人工智能。称之为控制器。
单位的生命值和攻击范围是在单位战斗时每局计算的。你可以改变这些数据,使虫鸣成为一个范围单位。称之为模型。
记住这个比喻,并将其扩展到MVC设计中。
最重要的是,在MVC设置中,控制器必须知道要调用哪个视图,但视图必须对控制器一无所知。
因此,您的视图必须为控制器提供一种通用的交互方式,这样您就可以让几个不同的控制器调用同一个视图(例如,作为参数提供的一些数据的标准化图形输出)。
这为您提供了灵活性:
- 如果您的客户想要的PDF输出您只提供HTML的输出,你可以逃脱惩罚编写要调用的新PDF视图从控制器参数作为HTML视图
- 如果您的客户想要不同数据源的类似HTML输出(例如),您可以编写一个新的控制器,为相同的旧HTML视图提供不同的数据集,该视图只提供相同的HTML报告和其他数据
如果您将视图与特定的控制器分离,并从控制器中了解要调用哪个视图,那么您就可以顺利完成任务了。
您的控制器应该定义绑定到视图实现的接口上定义的事件。
你如何去做这件事可能是棘手的部分。依赖项注入?景观工厂?让视图实例化它想要的控制器吗?这实际上取决于应用程序的复杂程度
对于一些非常快速和简单的东西,我会先让每个视图构造它的控制器,然后如果需要变大,可以考虑其他选项。就我个人而言,我认为一个完整的依赖注入框架对于六种表单来说太过分了:]