Qt中MVP架构与抽象DAO层的结合示例
前言
在之前的开发中,对于业务的解耦都是单独抽取出一个类,并且大量的业务逻辑写在ui类中,在学习了MVP架构模式后,尝试实现通过MVP(Model-View-Presenter)架构模式与抽象DAO(Data Access Object)层的结合,编写一个示例项目进行学习,具体的学习项目已上传git,地址:https://gitee.com/zbylalalala1/mvp_-study-demo.git。
一、MVP架构模式简介
MVP架构将应用程序分为三个核心组件:
- Model :负责业务逻辑和数据管理
- View :负责用户界面的展示和用户交互
- Presenter :作为Model和View之间的桥梁,处理业务逻辑并协调两者之间的通信
相比传统的MVC模式,MVP模式中的View更加被动,所有的业务逻辑都由Presenter处理,这使得单元测试变得更加容易。
二、整体架构设计
系统在传统MVP基础上增加了抽象DAO层,形成了如下的分层架构:
┌─────────────────┐
│ View │ 用户界面层
├─────────────────┤
│ Presenter │ 业务逻辑层
├─────────────────┤
│ Model │ 业务模型层
├─────────────────┤
│ IDeviceDAO │ 数据访问抽象层
├─────────────────┤
│ SqliteDeviceDAO │ 具体实现层
├─────────────────┤
│DatabaseManager │ 数据库管理层
└─────────────────┘
三、核心架构组件分析
3.1 抽象DAO层设计
抽象DAO层通过接口隔离了具体的数据访问实现:
// 抽象设备DAO接口
class IDeviceDAO : public QObject {
Q_OBJECT
public:
virtual ~IDeviceDAO() = default;
// 基本CRUD操作
virtual bool addDevice(const Device&
device) = 0;
virtual bool updateDevice(const Device&
device) = 0;
virtual bool deleteDevice(int id) = 0;
virtual Device getDeviceById(int id) = 0;
// 查询操作
virtual QList<Device> getAllDevices() = 0;
virtual QList<Device> searchDevices(const
QString& searchText) = 0;
virtual QList<Device> getDevicesByPage
(int page, int pageSize, const QString&
filter = "") = 0;
// 统计操作
virtual int getTotalCount(const QString&
filter = "") = 0;
// 初始化数据
virtual bool insertTestData() = 0;
virtual bool hasData() = 0;
signals:
void errorOccurred(const QString &error);
};
// SQLite具体实现类
class SqliteDeviceDAO : public IDeviceDAO {
Q_OBJECT
public:
explicit SqliteDeviceDAO(QObject *parent
= nullptr);
// 实现接口方法...
private:
DatabaseManager* m_dbManager;
Device queryToDevice(const QSqlQuery&
query);
};
3.2 Model层设计
Model层通过依赖倒置原则,依赖于抽象的IDeviceDAO接口而非具体实现:
class DeviceModel : public QObject {
Q_OBJECT
public:
explicit DeviceModel(QObject *parent =
nullptr);
~DeviceModel();
bool initialize();
QSqlQueryModel* getTableModel();
// 设备操作
bool addDevice(const Device& device);
bool updateDevice(const Device& device);
bool deleteDevice(int id);
// 搜索和过滤
void searchDevices(const QString&
searchText);
void resetFilter();
// 分页控制
void setPageSize(int pageSize);
void setCurrentPage(int page);
int getTotalPages() const;
signals:
void dataChanged();
void errorOccurred(const QString &error);
private:
IDeviceDAO* m_deviceDAO; // 使用接口指针,
实现依赖倒置
DatabaseManager* m_dbManager;
QSqlQueryModel* m_tableModel;
int m_pageSize;
int m_currentPage;
int m_totalRecords;
QString m_currentFilter;
void refreshData();
void updatePagination();
};
3.3 Presenter层设计
Presenter作为View和Model之间的协调者,实现了完全的事件驱动架构:
class DevicePresenter : public QObject {
Q_OBJECT
public:
explicit DevicePresenter(QObject *parent
= nullptr);
~DevicePresenter();
// 依赖注入接口
void setModel(DeviceModel* model);
void setView(DeviceView* view);
void connectSignals();
bool initialize();
private slots:
// 处理View的信号
void onSearchRequested(const QString&
searchText);
void onAddDeviceRequested();
void onEditDeviceRequested(int deviceId);
void onDeleteDeviceRequested(int
deviceId);
// 处理Model的信号
void onModelDataChanged();
void onModelErrorOccurred(const QString&
error);
private:
DeviceModel* m_model;
DeviceView* m_view;
bool m_initialized;
};
3.4 View层设计
View层通过信号-槽机制与Presenter通信,保持完全的被动性:
class DeviceView : public QWidget {
Q_OBJECT
public:
explicit DeviceView(QWidget *parent =
nullptr);
// 界面更新接口
void setTableModel(QAbstractItemModel*
model);
void updatePaginationInfo(int
currentPage, int totalPages, int
totalRecords, int pageSize);
// 用户输入接口
QString getSearchText() const;
int getSelectedPageSize() const;
signals:
// 用户操作信号
void searchRequested(const QString&
searchText);
void addDeviceRequested();
void editDeviceRequested(int deviceId);
void deleteDeviceRequested(int deviceId);
void pageChanged(int page);
void pageSizeChanged(int pageSize);
public slots:
void showMessage(const QString& message);
void showError(const QString& error);
};
四、依赖注入与生命周期管理
在main函数中,我们通过依赖注入的方式创建和管理各个组件:
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建Model
DeviceModel* model = new DeviceModel(&
app);
// 初始化Model
if (!model->initialize()) {
QMessageBox::critical(nullptr, "错误
", "无法初始化设备管理系统!");
return -1;
}
// 创建View
DeviceView* view = new DeviceView();
// 创建Presenter
DevicePresenter* presenter = new
DevicePresenter(&app);
// 依赖注入
presenter->setModel(model);
presenter->setView(view);
presenter->connectSignals();
// 初始化并启动
if (!presenter->initialize()) {
return -1;
}
view->show();
return app.exec();
}
浙公网安备 33010602011771号