界面架构- MVP(Qt)

[复制链接]
发表于 2025-10-2 00:51:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
MVP 架构详解

MVP 架构将传统的 MVC 模式进一步改进,重要目的是让视图(View)只管“被动”,全部业务逻辑都放在 Presenter 中,从而进步代码的测试性和可维护性。其三个焦点组件阐明如下:


  • Model(模子)
    Model 负责应用的业务逻辑和数据处置惩罚。在本示例中,Model 提供一个接口用于盘算字符串的长度。Model 与用户界面完全无关,仅关注数据和业务规则。
  • View(视图)
    View 负责构建用户界面,展示数据,并将用户的操纵事故(比方按钮点击)通报给 Presenter。为了低落耦合,通常会界说一个 View 接口(比方 IView),而详细的 View(比方 MainWindow)实现这个接口。View 只负责展示,不直接包罗业务逻辑。
  • Presenter(表现层/中介者)
    Presenter 作为中介者毗连 Model 与 View。它吸收来自 View 的用户操纵,调用 Model 举行数据处置惩罚,再将处置惩罚效果反馈给 View 更新表现。Presenter 中的逻辑通常是纯 C++ 类,不依靠于详细的 GUI 组件,因此便于单位测试。
这种架构的优点在于:


  • 关注点分离:业务逻辑与界面展示完全解耦。
  • 进步可测试性:Presenter 逻辑可以独立测试,View 尽大概简单。
  • 便于维护和扩展:每一层职责明白,修改此中一层对别的层影响较小。
示例

示例功能

构建一个简单的应用,界面包罗:


  • QLineEdit:供用户输入字符串;
  • QPushButton:当用户点击按钮时,盘算 QLineEdit 中文本的字符数;
  • QLabel:表现盘算后的字符数。
团体流程:

  • 用户在 QLineEdit 中输入字符串;
  • 点击按钮,触发控制器;
  • 控制器调用模子盘算字符串长度;
  • 控制器将盘算效果更新到 QLabel 表现出来。
示例代码

下面给出各个组件的示例代码,代码按照 MVP 的头脑分为四个部分:


  • 界说 View 接口
    起首界说一个纯虚接口,规定 View 应实现的更新表现接口。
  1. // IView.h
  2. #ifndef IVIEW_H
  3. #define IVIEW_H
  4. #include <QString>
  5. class IView
  6. {
  7. public:
  8.     virtual ~IView() {}
  9.     // 更新显示结果,例如将计算的长度写入 QLabel
  10.     virtual void updateResult(const QString &result) = 0;
  11. };
  12. #endif // IVIEW_H
复制代码


  • 界说 Model 类
    Model 只负责业务逻辑,这里只提供盘算字符串长度的方法
  1. // Model.h
  2. #ifndef MODEL_H
  3. #define MODEL_H
  4. #include <QString>
  5. class Model
  6. {
  7. public:
  8.     Model() {}
  9.     // 计算并返回字符串的长度
  10.     int getTextLength(const QString &text) {
  11.         return text.length();
  12.     }
  13. };
  14. #endif // MODEL_H
复制代码


  • 界说 Presenter 类
    Presenter 负责吸收 View 传来的哀求,调用 Model 处置惩罚,再关照 View 更新表现。
  1. // Presenter.h
  2. #ifndef PRESENTER_H
  3. #define PRESENTER_H
  4. #include "IView.h"
  5. #include "Model.h"
  6. #include <QString>
  7. class Presenter
  8. {
  9. public:
  10.     Presenter(IView *view, Model *model)
  11.         : m_view(view), m_model(model) {}
  12.     // 处理按钮点击事件,计算文本长度并通知 View 更新显示
  13.     void onCalculateButtonClicked(const QString &inputText) {
  14.         int length = m_model->getTextLength(inputText);
  15.         m_view->updateResult("长度:" + QString::number(length));
  16.     }
  17. private:
  18.     IView *m_view;
  19.     Model *m_model;
  20. };
  21. #endif // PRESENTER_H
复制代码


  • 实现详细 View(MainWindow)
    MainWindow 继续自 QWidget 并实现 IView 接口,构建界面,同时将用户操纵(按钮点击)转发给 Presenter。
  1. // MainWindow.h
  2. #ifndef MAINWINDOW_H
  3. #define MAINWINDOW_H
  4. #include <QWidget>
  5. #include "IView.h"
  6. class QLineEdit;
  7. class QPushButton;
  8. class QLabel;
  9. class Presenter;
  10. class Model;
  11. class MainWindow : public QWidget, public IView
  12. {
  13.     Q_OBJECT
  14. public:
  15.     explicit MainWindow(QWidget *parent = nullptr);
  16.     ~MainWindow();
  17.     // IView 接口实现:更新 QLabel 显示计算结果
  18.     void updateResult(const QString &result) override;
  19. private slots:
  20.     // 当按钮点击时,调用 Presenter 处理
  21.     void handleCalculateButton();
  22. private:
  23.     QLineEdit *m_lineEdit;
  24.     QPushButton *m_button;
  25.     QLabel *m_label;
  26.     // MVP 的其它组件
  27.     Presenter *m_presenter;
  28.     Model *m_model;
  29. };
  30. #endif // MAINWINDOW_H
复制代码
  1. // MainWindow.cpp
  2. #include "MainWindow.h"
  3. #include "Presenter.h"
  4. #include "Model.h"
  5. #include <QLineEdit>
  6. #include <QPushButton>
  7. #include <QLabel>
  8. #include <QVBoxLayout>
  9. MainWindow::MainWindow(QWidget *parent)
  10.     : QWidget(parent)
  11. {
  12.     // 创建控件
  13.     m_lineEdit = new QLineEdit(this);
  14.     m_button = new QPushButton("计算长度", this);
  15.     m_label = new QLabel("结果显示", this);
  16.     // 布局管理
  17.     QVBoxLayout *layout = new QVBoxLayout(this);
  18.     layout->addWidget(m_lineEdit);
  19.     layout->addWidget(m_button);
  20.     layout->addWidget(m_label);
  21.     setLayout(layout);
  22.     // 创建 Model 与 Presenter
  23.     m_model = new Model();
  24.     m_presenter = new Presenter(this, m_model);
  25.     // 连接按钮点击信号到槽函数
  26.     connect(m_button, &QPushButton::clicked, this, &MainWindow::handleCalculateButton);
  27. }
  28. MainWindow::~MainWindow()
  29. {
  30.     delete m_presenter;
  31.     delete m_model;
  32. }
  33. void MainWindow::updateResult(const QString &result)
  34. {
  35.     // 更新 QLabel 显示计算结果
  36.     m_label->setText(result);
  37. }
  38. void MainWindow::handleCalculateButton()
  39. {
  40.     // 获取用户输入
  41.     QString inputText = m_lineEdit->text();
  42.     // 将输入传递给 Presenter 处理
  43.     m_presenter->onCalculateButtonClicked(inputText);
  44. }
复制代码


  • 主函数入口
    在 main 函数中创建 QApplication 对象并表现 MainWindow。
  1. // main.cpp
  2. #include <QApplication>
  3. #include "MainWindow.h"
  4. int main(int argc, char *argv[])
  5. {
  6.     QApplication app(argc, argv);
  7.     MainWindow window;
  8.     window.setWindowTitle("Qt MVP 示例");
  9.     window.resize(300, 200);
  10.     window.show();
  11.     return app.exec();
  12. }
复制代码
总结

在上述 MVP 示例中,我们将应用步调分为三个部分:


  • Model 负责盘算字符串的长度,不依靠于任何界面;
  • View(MainWindow)构建用户界面,展示 QLineEdit、按钮和 QLabel,并实现 IView 接口,用于吸收 Presenter 的更新关照;
  • Presenter 吸收 View 的操纵哀求,调用 Model 盘算效果,再将效果通报回 View 更新界面。
这种计划使得业务逻辑与界面展示彻底分离,便于单位测试 Presenter 以及在项目中对各模块举行独立开辟和维护。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表