1

让我们假设您有一个全屏 C++ 桌面应用程序,它由几个屏幕组成,每个屏幕都有不同的功能,以及一个带有适当模型的 ViewController。例如以下一组非常简化的屏幕:

  1. 测验:用户通过一组多项选择题进行导航。
  2. 统计测验结果。
  3. 信息:向用户提供有关特定主题的信息。
  4. 菜单(测验、信息、退出)

根据 GRASP 原理Information Expert判断,每个 ViewController 将最清楚何时完成以及何时移动到新屏幕。然而,根据同样的原则,它不是决定下一个屏幕实际上应该是什么的正确位置。在这个相当简单的例子中,人们可能会说这没问题,但在更复杂的应用程序中,它无疑会导致重复的代码和逻辑以及更高的耦合和更低的内聚。还有一个问题是您必须在当前屏幕的 ViewController 中创建新的小部件和控制器,这会带来各种新问题,至少根据Creator原则,这不是正确的选择。您将不得不引入一个工厂来缓解一些问题,等等。

因此,下一个合乎逻辑的步骤是引入一个 ApplicationController 来单独负责管理视图及其控制器,包括从一个视图到下一个视图的导航流。

在我看来,这仍然存在一个问题:如何向 ApplicationController 发出信号,表明是时候移动到不同的屏幕并将控制权正确地移交给该对象了?

例如,可以使用观察者模式。但是,如果您现在有一个昂贵的 View 处于活动状态,并且希望在新屏幕处于活动状态后将其销毁怎么办?如果当前的 ViewController 向 ApplicationController 发出下一个屏幕应该打开的信号,它可以管理所有内容,直到它会破坏当前活动的屏幕,因为当前的调用完全来自该对象,所以它无法做到这一点。除了这种方法的其他几个问题。

所以我的问题是(对所有冗长的介绍感到抱歉:P):您如何使用 MVC 正确实现从一个全屏小部件到另一个全屏小部件的导航流程,从而解决上述问题,在 View- 和 ApplicationController 和在耦合和内聚方面很好地面向对象吗?

4

1 回答 1

0

有时,您在思考过程中遗漏了一个细节,而您打开了一整套问题,甚至没有意识到自己犯了错误。

在这种情况下,细节是您可以自然地发布异步和同步事件。如果您必须确保您不再处于事件发布方法的上下文中,请发布异步事件。在处理程序中收到该事件后,您可以确定上下文已被保留。例如,如果您愿意,您可以安全地删除该对象。自然,事件处理程序不应位于您尝试删除的同一对象的上下文中。

为了完整性:在 Qt 中,您可以为使用 connect() 创建的每个信号/插槽连接指定它应该是 Qt::QueuedConnection 类型。如果您提出一个信号,它不会被传递,直到控制返回到线程的事件循环。通常,使用 Qt::AutoConnection,如果接收器在同一个线程中,则在它被提升时传递一个信号(Qt::DirectConnection),或者如果接收器在,则回退到对该信号排队(Qt::QueuedConnection)一个不同的线程。

在 wxWidgets 中,您可以使用 wxEvtHandler::QueueEvent(wxEvent* event) 对事件进行排队,例如可以通过 Application 单例获得。

于 2012-05-29T13:51:44.840 回答