【发布时间】:2011-04-28 09:51:57
【问题描述】:
我正在研究模型-视图-控制器设计模式,我从理论上理解了该模式背后的概念,但我想看看如何将其付诸实践。
Wikipedia 提到了 Wt - Web 工具包、CppCMS 和其他一些使用该模式的标准实现,但是我并不熟悉这些,我只是希望和
如果有人可以提供一些示例代码(希望是 C++)来实现该模式并解释该模式的理论被付诸实践,将不胜感激。
【问题讨论】:
标签: c++ design-patterns oop
我正在研究模型-视图-控制器设计模式,我从理论上理解了该模式背后的概念,但我想看看如何将其付诸实践。
Wikipedia 提到了 Wt - Web 工具包、CppCMS 和其他一些使用该模式的标准实现,但是我并不熟悉这些,我只是希望和
如果有人可以提供一些示例代码(希望是 C++)来实现该模式并解释该模式的理论被付诸实践,将不胜感激。
【问题讨论】:
标签: c++ design-patterns oop
可以基于 MVC 设计一个简单的文本编辑器。将string 类视为存储数据的模型。我们可能有一个名为SimpleTextView 的类,它按原样显示附加到它的string 中的文本。一个名为KeyboardEventHandler 的类可以充当控制器。控制器将通知视图有关新的键盘事件。视图反过来修改模型(如附加或删除文本)。模型中的更改会反映在附加到它的所有视图上。例如,可能有另一个名为HtmlView 的视图附加到从SimpleTextView 中操作的string 对象。如果用户在SimpleTextView 中输入有效的HTML 标签,HtmlView 将实时显示格式化输出。
【讨论】:
在我编写的 Python 3.x 编程介绍的第 2 章中,有几个完整的 MVC 示例和讨论(我还没有完成第 3 章等,该项目已经搁置了一段时间 - - 当我发现我写 Python 可能不适合非常大规模的开发时,Python 社区真的很喜欢愤怒的蜜蜂群,因此很难获得明智的反馈)。可从Google Docs 获取 PDF 格式。我不知道它与常见的 MVC 实现的映射情况如何,我主要关心的是如何理解总体思路。 :-)
干杯,
PS:PDF 文件中有一个很好的目录,但 Google Docs 没有显示它。您需要 dl 并使用 Foxit 或 Acrobat 或其他一些 PDF 查看器。我认为 Google Docs 上有一个单独的可查看目录,但尚未检查,也不记得是否更新了。
PPS:忘了提一下,接近结尾的 MVC 图像处理示例有 Lena Söderberg 的漂亮图片! :)
【讨论】:
这是我做的一个简单的例子(没有尝试编译它,如果有错误请告诉我):
class Button; // Prewritten GUI element
class GraphGUI {
public:
GraphGUI() {
_button = new Button("Click Me");
_model = new GraphData();
_controller = new GraphController(_model, _button);
}
~GraphGUI() {
delete _button;
delete _model;
delete _controller;
}
drawGraph() {
// Use model's data to draw the graph somehow
}
...
private:
Button* _button;
GraphData* _model;
GraphController* _controller;
};
class GraphData {
public:
GraphData() {
_number = 10;
}
void increaseNumber() {
_number += 10;
}
const int getNumber() { return _number; }
private:
int _number;
};
class GraphController {
public:
GraphController(GraphData* model, Button* button) {
__model = model;
__button = button;
__button->setClickHandler(this, &onButtonClicked);
}
void onButtonClicked() {
__model->increaseNumber();
}
private:
// Don't handle memory
GraphData* __model;
Button* __button;
};
忽略 Button 的实现,基本上这个程序会使用 GraphGUI 来显示一个在按下按钮时会发生变化的图形。假设它是一个条形图,它会变得更高。
由于模型独立于视图(按钮),而控制器处理两者之间的通信,这遵循 MVC 模式。
当按钮被点击时,控制器通过 onButtonClicked 函数修改模型,Button 类知道在被点击时会调用该函数。
这样做的美妙之处在于模型和视图是完全独立的,每个的实现都可以发生巨大变化并且不会影响另一个,控制器可能只需要进行一些更改。如果这种情况下的模型根据一些数据库数据计算出一些结果,那么单击按钮可能会导致这种情况发生,但按钮实现不必更改。或者,当点击发生时,它可以告诉控制器鼠标悬停在按钮上时,而不是告诉控制器。无论是什么触发了更改,都会对模型应用相同的更改。
【讨论】:
GraphGUI::OnButtonClick() 函数,以及一个带有GraphGUI::ShowMessage() 的消息面板,它应该显示文本“绘制图形...” ,在哪种情况下会调用GraphGUI::ShowMessage() 函数? 1)GraphGUI::OnButtonClick()直接调用GraphGUI::ShowMessage()。 2) GraphGUI::OnButtonClick() 调用GraphController::onButtonClicked(),然后GraphController::onButtonClicked() 调用GraphGUI::ShowMessage()。
_button vs __button 等,后者不能用作保留相邻下划线的标识符。此外,GraphGui 似乎存在身份危机。是图形用户界面吗?然后它是一个视图,不应该拥有/知道模型/控制器。然而,它似乎试图同时成为控制器的一部分并拥有“其他”控制器和模型——更糟糕的是——通过动态分配和原始new/delete,这很可能是不必要的。对我来说(A)所有权根本不是必需的,但是(B)如果有原因,它一定不能由 View 完成,只能由 Controller 完成
代码是理解和学习模型视图控制器的最佳途径:
这是一个简单的 JS 示例(来自Wiki)
/** Model, View, Controller */
var M = {}, V = {}, C = {};
/** Model stores data */
M.data = "hello world";
/** View controls what to present */
V.render = (M) => { alert(M.data); }
/** Controller bridges View and Model */
C.handleOnload = () => { V.render(M); }
/** Controller on Windows OnLoad event */
window.onload = C.handleOnload;
这是 C/C++ 的详细帖子 Model-View-Controller Explained in C++
【讨论】: