马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
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 应实现的更新表现接口。
- // IView.h
- #ifndef IVIEW_H
- #define IVIEW_H
- #include <QString>
- class IView
- {
- public:
- virtual ~IView() {}
- // 更新显示结果,例如将计算的长度写入 QLabel
- virtual void updateResult(const QString &result) = 0;
- };
- #endif // IVIEW_H
复制代码
- 界说 Model 类
Model 只负责业务逻辑,这里只提供盘算字符串长度的方法
- // Model.h
- #ifndef MODEL_H
- #define MODEL_H
- #include <QString>
- class Model
- {
- public:
- Model() {}
- // 计算并返回字符串的长度
- int getTextLength(const QString &text) {
- return text.length();
- }
- };
- #endif // MODEL_H
复制代码
- 界说 Presenter 类
Presenter 负责吸收 View 传来的哀求,调用 Model 处置惩罚,再关照 View 更新表现。
- // Presenter.h
- #ifndef PRESENTER_H
- #define PRESENTER_H
- #include "IView.h"
- #include "Model.h"
- #include <QString>
- class Presenter
- {
- public:
- Presenter(IView *view, Model *model)
- : m_view(view), m_model(model) {}
- // 处理按钮点击事件,计算文本长度并通知 View 更新显示
- void onCalculateButtonClicked(const QString &inputText) {
- int length = m_model->getTextLength(inputText);
- m_view->updateResult("长度:" + QString::number(length));
- }
- private:
- IView *m_view;
- Model *m_model;
- };
- #endif // PRESENTER_H
复制代码
- 实现详细 View(MainWindow)
MainWindow 继续自 QWidget 并实现 IView 接口,构建界面,同时将用户操纵(按钮点击)转发给 Presenter。
- // MainWindow.h
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include <QWidget>
- #include "IView.h"
- class QLineEdit;
- class QPushButton;
- class QLabel;
- class Presenter;
- class Model;
- class MainWindow : public QWidget, public IView
- {
- Q_OBJECT
- public:
- explicit MainWindow(QWidget *parent = nullptr);
- ~MainWindow();
- // IView 接口实现:更新 QLabel 显示计算结果
- void updateResult(const QString &result) override;
- private slots:
- // 当按钮点击时,调用 Presenter 处理
- void handleCalculateButton();
- private:
- QLineEdit *m_lineEdit;
- QPushButton *m_button;
- QLabel *m_label;
- // MVP 的其它组件
- Presenter *m_presenter;
- Model *m_model;
- };
- #endif // MAINWINDOW_H
复制代码- // MainWindow.cpp
- #include "MainWindow.h"
- #include "Presenter.h"
- #include "Model.h"
- #include <QLineEdit>
- #include <QPushButton>
- #include <QLabel>
- #include <QVBoxLayout>
- MainWindow::MainWindow(QWidget *parent)
- : QWidget(parent)
- {
- // 创建控件
- m_lineEdit = new QLineEdit(this);
- m_button = new QPushButton("计算长度", this);
- m_label = new QLabel("结果显示", this);
- // 布局管理
- QVBoxLayout *layout = new QVBoxLayout(this);
- layout->addWidget(m_lineEdit);
- layout->addWidget(m_button);
- layout->addWidget(m_label);
- setLayout(layout);
- // 创建 Model 与 Presenter
- m_model = new Model();
- m_presenter = new Presenter(this, m_model);
- // 连接按钮点击信号到槽函数
- connect(m_button, &QPushButton::clicked, this, &MainWindow::handleCalculateButton);
- }
- MainWindow::~MainWindow()
- {
- delete m_presenter;
- delete m_model;
- }
- void MainWindow::updateResult(const QString &result)
- {
- // 更新 QLabel 显示计算结果
- m_label->setText(result);
- }
- void MainWindow::handleCalculateButton()
- {
- // 获取用户输入
- QString inputText = m_lineEdit->text();
- // 将输入传递给 Presenter 处理
- m_presenter->onCalculateButtonClicked(inputText);
- }
复制代码
- 主函数入口
在 main 函数中创建 QApplication 对象并表现 MainWindow。
- // main.cpp
- #include <QApplication>
- #include "MainWindow.h"
- int main(int argc, char *argv[])
- {
- QApplication app(argc, argv);
- MainWindow window;
- window.setWindowTitle("Qt MVP 示例");
- window.resize(300, 200);
- window.show();
- return app.exec();
- }
复制代码 总结
在上述 MVP 示例中,我们将应用步调分为三个部分:
- Model 负责盘算字符串的长度,不依靠于任何界面;
- View(MainWindow)构建用户界面,展示 QLineEdit、按钮和 QLabel,并实现 IView 接口,用于吸收 Presenter 的更新关照;
- Presenter 吸收 View 的操纵哀求,调用 Model 盘算效果,再将效果通报回 View 更新界面。
这种计划使得业务逻辑与界面展示彻底分离,便于单位测试 Presenter 以及在项目中对各模块举行独立开辟和维护。
|