3

对我来说,一个好的 MVC 实现的试金石是换出视图是多么容易。由于懒惰,我总是做得非常糟糕,但现在我想把它做好。这是在 C++ 中,但如果我相信炒作的话,它应该同样适用于非桌面应用程序。

下面是一个例子:应用程序控制器必须在后台检查某个 URL 是否存在。它可能会连接到“URL 可用”事件(使用 Boost Signals),如下所示:

BackgroundUrlCheckerThread(Controller & controller)
{
   // ...
   signalUrlAvailable.connect(
      boost::bind(&Controller::urlAvailable,&controller,_1))
}

那么它Controller::urlAvailable看起来像什么?

这是一种可能性:

void
Controller::urlAvailable(Url url)
{
    if(!view->askUser("URL available, wanna download it?"))
      return;
    else
      // Download the url in a new thread, repeat
}

对我来说,这似乎是视图和控制器的严重耦合。这样的耦合使得在使用 web 时无法实现视图(协程除外)。

另一种可能:

void
Controller::urlAvailable(Url url)
{
   urlAvailableSignal(url); // Now, any view interested can do what it wants
}

我偏爱后者,但如果我这样做,似乎会有:

  1. 400 亿个这样的信号。对于非平凡的应用程序,应用程序控制器可能会变得很大
  2. 给定视图意外忽略某些信号的非常现实的可能性(API 可以在链接时通知您,但信号/插槽是运行时的)

那么您建议如何消除耦合并降低复杂性?提前致谢。

4

2 回答 2

4
于 2010-04-07T02:35:31.177 回答
0

您可以使用“m”模型将它们解耦,并使用(在概念上)类似命令的模式和侦听器模式来降低复杂性。

所以你的控制器可能看起来像这样:

void
Controller::urlAvailable(Url url)
{
   Controller::fireSignal("urlAvailable", url, ... other possible parameter);
}
Controller::fireSignal(char* cmd, Url url, ... other possible parameters) {
   Model &M   = new Model();
   M->command = cmd;
   M->url     = url;
   M-> ... other possible
   for(int v = Controller::ViewCount; --v >= 0; )
      Controller::Views[v]->notice(M);
}

注意:我不是 C++ 程序员,所以请原谅我的错误语法。

MVC 的整个想法是使用 M(odel) 将 C(ontrol) 与 V(iew) 解耦。该示例非常简化。更实际的一种是对不同种类的相似信号使用不同的模型。

希望这可以帮助。

于 2010-04-07T02:00:06.103 回答