关于在创建 GUI 时将视图与逻辑分离的问题,我有很多问题要发布。
以下是我将使用“Humble Dialog”方法为具有标签和按钮的简单对话框执行的操作的最小示例。按下按钮应在标签上显示一些文本。我使用了 C++ 和我熟悉的 Qt,但我想所有其他观众都可以阅读它。
无论如何,由于语言的选择,我对可能的副作用感兴趣(我在项目中使用 C++,我有兴趣介绍这一点)。
class IView {
public:
IView(){}
virtual ~IView(){}
virtual void showResult(const QString &text)=0;
};
class Presenter {
public:
Presenter(IView *view){
m_View = view;
}
~Presenter(){}
void buttonPressed(){
QString text;
// Evaluate text
m_View->showResult(text);
}
private:
IView *m_View;
}
// Multiple inheritance. Is this OK?
class MyView : public QDialog, public IView {
public:
MyView(){
m_Presenter = new Presenter(this);
m_Button = new QPushbutton(this);
m_Label = new QLabel(this);
// Ui event handled inside view but then directly
// propagated to the Presenter
connect(m_Button,SIGNAL(clicked()),this,SLOT(buttonPressed()));
}
~MyView(){
delete m_Presenter;
// Qt will automatically delete m_Button and m_Label;
}
void showResult(const QString &text){
m_Label->setText(text);
}
protected slots:
void buttonPressed(){
m_Presenter->buttonPressed();
}
private:
Presenter *m_Presenter;
QPushbutton *m_Button;
QLabel *m_Label;
}
class TestView : public IView {
public:
TestView(){}
~TestView(){}
void showResult(const QString &text){
m_LabelText = text;
}
QString getResult(){
return m_LabelText;
}
private:
QString m_LabelText;
}
// Test code
TestView view;
Presenter presenter(&view);
presenter.buttonPressed();
EXPECT_EQ(view.getResult(),"Expected Result");
// Procuction code
MyView view;
view.show();
现在,这就是我按照Feathers 对 Humble 对话框的初步工作得到的结果。我从Fowler 的实现中得到的方法是避免在 MyView 的构造函数中创建 Presenter 类的实例,而是将其作为参数传递,这样生产代码就会看起来像测试代码。我个人喜欢我在这里介绍的方法。
所以,
- 它是否意味着与多重继承一起使用(请参阅我在 MyView 类中的评论)?
- 事件应该直接传播到 Presenter 还是应该在将调用相应 Presenter 操作的视图中处理(正如我在此处所做的那样,以避免必须将 Presenter 设为 QObject 以便它可以处理 UI 事件)?
- 有没有其他说明?