当前位置: 首页 > news >正文

【Qt】 设计模式

在Qt应用程序开发中,结合数据库操作、通信、界面逻辑和显示等功能,以下是常用的设计模式及其典型应用场景:

一、MVC/MVVM(模型-视图-控制器/视图模型)

作用:分离数据(模型)、界面(视图)和业务逻辑(控制器/视图模型),提升可维护性。
Qt实现

  • MVC:Qt提供QAbstractItemModelQListView/QTableView等组件,支持数据与视图分离。
  • MVVM:结合Qt的属性系统和信号槽,通过QObjectQ_PROPERTY实现视图模型。

典型场景

  • 数据库查询结果的表格展示(如QSqlTableModelQTableView结合)。
  • 表单数据的双向绑定(视图变化自动更新模型,反之亦然)。

示例代码

// 模型(数据库操作)
QSqlTableModel model;
model.setTable("users");
model.select();// 视图(界面显示)
QTableView tableView;
tableView.setModel(model);// 控制器(业务逻辑,如按钮点击事件)
QPushButton deleteButton("删除选中行");
connect(&deleteButton, &QPushButton::clicked, [&]() {QModelIndexList selected = tableView.selectedIndexes();if (!selected.isEmpty()) {model.removeRow(selected.first().row());model.submitAll();  // 提交到数据库}
});

二、单例模式(Singleton)

作用:确保一个类只有一个实例,并提供全局访问点。
典型场景

  • 数据库连接管理(避免重复创建连接)。
  • 全局配置管理器。
  • 网络通信模块(如唯一的WebSocket客户端)。

示例代码

class DatabaseManager {
public:static DatabaseManager& getInstance() {static DatabaseManager instance;  // 线程安全的单例实现return instance;}QSqlDatabase getDatabase() {return db;}private:DatabaseManager() {db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("mydatabase.db");if (!db.open()) {qDebug() << "Database error:" << db.lastError().text();}}~DatabaseManager() {if (db.isOpen()) {db.close();}}QSqlDatabase db;Q_DISABLE_COPY(DatabaseManager)  // 禁止拷贝构造和赋值
};

三、观察者模式(Observer)

作用:对象间的一对多依赖关系,当一个对象状态变化时,所有依赖者自动收到通知。
Qt实现:基于信号槽机制。
典型场景

  • 数据库数据更新时通知界面刷新。
  • 网络通信中接收到新消息时通知相关模块。
  • 多窗口间的数据同步。

示例代码

// 数据模型(被观察对象)
class DataModel : public QObject {Q_OBJECT
public:void updateData(const QString& newData) {m_data = newData;emit dataChanged(m_data);  // 发送信号通知观察者}signals:void dataChanged(const QString& data);private:QString m_data;
};// 视图(观察者)
class DataView : public QLabel {Q_OBJECT
public:explicit DataView(QWidget* parent = nullptr) : QLabel(parent) {connect(&model, &DataModel::dataChanged, this, &DataView::updateDisplay);}private slots:void updateDisplay(const QString& data) {setText(data);  // 更新界面显示}private:DataModel model;
};

四、工厂模式(Factory)

作用:通过工厂类创建对象,解耦对象的创建和使用。
典型场景

  • 根据配置动态创建不同类型的数据库连接(如MySQL、SQLite)。
  • 网络通信协议的抽象(如HTTP、WebSocket、MQTT)。

示例代码

// 抽象产品:数据库连接
class DatabaseConnection {
public:virtual bool open() = 0;virtual void close() = 0;virtual ~DatabaseConnection() {}
};// 具体产品:MySQL连接
class MySQLConnection : public DatabaseConnection {
public:bool open() override { /* 实现MySQL连接逻辑 */ }void close() override { /* 实现MySQL关闭逻辑 */ }
};// 具体产品:SQLite连接
class SQLiteConnection : public DatabaseConnection {
public:bool open() override { /* 实现SQLite连接逻辑 */ }void close() override { /* 实现SQLite关闭逻辑 */ }
};// 工厂类
class DatabaseFactory {
public:static DatabaseConnection* createConnection(const QString& type) {if (type == "mysql") {return new MySQLConnection();} else if (type == "sqlite") {return new SQLiteConnection();}return nullptr;}
};

五、命令模式(Command)

作用:将请求封装为对象,支持请求的参数化、排队、记录和撤销。
典型场景

  • 数据库操作的批量执行(如事务中的多个增删改查)。
  • 撤销/重做功能的实现。

示例代码

// 抽象命令
class Command {
public:virtual void execute() = 0;virtual void undo() = 0;virtual ~Command() {}
};// 具体命令:数据库插入
class InsertCommand : public Command {
public:InsertCommand(QSqlDatabase& db, const QString& table, const QVariantMap& data): m_db(db), m_table(table), m_data(data) {}void execute() override {// 执行插入操作QSqlQuery query(m_db);QString fields = m_data.keys().join(", ");QString placeholders = QStringList(m_data.size(), "?").join(", ");query.prepare(QString("INSERT INTO %1 (%2) VALUES (%3)").arg(m_table, fields, placeholders));int i = 0;for (const auto& value : m_data.values()) {query.bindValue(i++, value);}m_success = query.exec();m_lastInsertId = query.lastInsertId();}void undo() override {// 撤销插入(删除刚插入的记录)if (m_success && m_lastInsertId.isValid()) {QSqlQuery query(m_db);query.prepare(QString("DELETE FROM %1 WHERE id = ?").arg(m_table));query.bindValue(0, m_lastInsertId);query.exec();}}private:QSqlDatabase& m_db;QString m_table;QVariantMap m_data;bool m_success = false;QVariant m_lastInsertId;
};

六、状态模式(State)

作用:允许对象在内部状态改变时改变其行为,将状态逻辑封装到不同的状态类中。
典型场景

  • 网络连接状态管理(如未连接、连接中、已连接、断开)。
  • 数据库操作的状态流转(如事务的开始、提交、回滚)。

示例代码

// 抽象状态
class ConnectionState {
public:virtual void connect() = 0;virtual void disconnect() = 0;virtual void sendData(const QByteArray& data) = 0;virtual ~ConnectionState() {}
};// 具体状态:未连接
class DisconnectedState : public ConnectionState {
public:void connect() override {// 执行连接逻辑qDebug() << "Connecting...";// 连接成功后切换到ConnectedState}void disconnect() override {qDebug() << "Already disconnected";}void sendData(const QByteArray& data) override {qDebug() << "Cannot send data: not connected";}
};// 上下文类
class NetworkConnection {
public:void setState(ConnectionState* state) {delete m_state;m_state = state;}void connect() { m_state->connect(); }void disconnect() { m_state->disconnect(); }void sendData(const QByteArray& data) { m_state->sendData(data); }private:ConnectionState* m_state = new DisconnectedState();
};

七、代理模式(Proxy)

作用:为其他对象提供一种代理以控制对这个对象的访问。
典型场景

  • 数据库操作的权限控制(如只读代理、读写代理)。
  • 网络请求的缓存代理(避免重复请求相同数据)。

示例代码

// 抽象主题:数据库操作
class DatabaseOperations {
public:virtual QSqlQuery executeQuery(const QString& sql) = 0;virtual ~DatabaseOperations() {}
};// 真实主题:实际数据库操作
class RealDatabaseOperations : public DatabaseOperations {
public:explicit RealDatabaseOperations(const QSqlDatabase& db) : m_db(db) {}QSqlQuery executeQuery(const QString& sql) override {QSqlQuery query(m_db);query.exec(sql);return query;}private:QSqlDatabase m_db;
};// 代理:只读权限代理
class ReadOnlyDatabaseProxy : public DatabaseOperations {
public:explicit ReadOnlyDatabaseProxy(DatabaseOperations* realOps) : m_realOps(realOps) {}QSqlQuery executeQuery(const QString& sql) override {// 检查是否为只读操作(如SELECT语句)if (sql.trimmed().toUpper().startsWith("SELECT")) {return m_realOps->executeQuery(sql);} else {qDebug() << "Read-only proxy: write operations are not allowed";return QSqlQuery();}}private:DatabaseOperations* m_realOps;
};

八、策略模式(Strategy)

作用:定义一系列算法,将每个算法封装起来,并使它们可以相互替换。
典型场景

  • 根据配置选择不同的数据库加密策略。
  • 网络通信中根据网络状态选择不同的传输协议(如WiFi用HTTP,4G用WebSocket)。

示例代码

// 抽象策略:数据加密
class EncryptionStrategy {
public:virtual QByteArray encrypt(const QByteArray& data) = 0;virtual QByteArray decrypt(const QByteArray& data) = 0;virtual ~EncryptionStrategy() {}
};// 具体策略:AES加密
class AESEncryption : public EncryptionStrategy {
public:QByteArray encrypt(const QByteArray& data) override {// 实现AES加密逻辑return "AES-encrypted:" + data;}QByteArray decrypt(const QByteArray& data) override {// 实现AES解密逻辑return data.mid(11);  // 移除"AES-encrypted:"前缀}
};// 具体策略:Base64编码(非加密)
class Base64Encoding : public EncryptionStrategy {
public:QByteArray encrypt(const QByteArray& data) override {return data.toBase64();}QByteArray decrypt(const QByteArray& data) override {return QByteArray::fromBase64(data);}
};// 上下文类
class DataManager {
public:void setEncryptionStrategy(EncryptionStrategy* strategy) {delete m_strategy;m_strategy = strategy;}QByteArray saveData(const QByteArray& data) {return m_strategy->encrypt(data);}QByteArray loadData(const QByteArray& encryptedData) {return m_strategy->decrypt(encryptedData);}private:EncryptionStrategy* m_strategy = new Base64Encoding();
};

九、组合模式(Composite)

作用:将对象组合成树形结构以表示“部分-整体”的层次结构,使用户对单个对象和组合对象的使用具有一致性。
典型场景

  • 复杂UI界面的组件管理(如窗口包含多个面板,面板包含多个控件)。
  • 数据库查询条件的组合(如AND/OR逻辑组合多个查询条件)。

示例代码

// 抽象组件:查询条件
class QueryCondition {
public:virtual QString toSql() = 0;virtual ~QueryCondition() {}
};// 叶子节点:简单条件
class SimpleCondition : public QueryCondition {
public:SimpleCondition(const QString& field, const QString& op, const QVariant& value): m_field(field), m_op(op), m_value(value) {}QString toSql() override {return QString("%1 %2 '%3'").arg(m_field, m_op, m_value.toString());}private:QString m_field;QString m_op;QVariant m_value;
};// 组合节点:复合条件
class CompositeCondition : public QueryCondition {
public:enum Logic { AND, OR };explicit CompositeCondition(Logic logic) : m_logic(logic) {}void addCondition(QueryCondition* condition) {m_conditions.append(condition);}QString toSql() override {if (m_conditions.isEmpty()) return "";QString sql = "(";for (int i = 0; i < m_conditions.size(); ++i) {sql += m_conditions[i]->toSql();if (i < m_conditions.size() - 1) {sql += (m_logic == AND) ? " AND " : " OR ";}}sql += ")";return sql;}private:Logic m_logic;QList<QueryCondition*> m_conditions;
};

总结:设计模式选择指南

功能模块推荐设计模式原因
数据库操作MVC/MVVM、单例、命令、工厂分离数据与视图,统一数据库连接,支持批量操作和多数据库适配
网络通信单例、观察者、状态、策略全局唯一连接,监听消息变化,管理连接状态,动态切换协议
界面逻辑与显示MVC/MVVM、观察者、组合分离界面与数据,实现界面间通信,管理复杂UI结构
权限与缓存控制代理模式控制对资源的访问,缓存频繁请求的数据
配置与扩展性工厂、策略、抽象工厂根据配置动态创建对象,灵活切换算法或数据库类型

建议

  1. 优先使用Qt框架内置的模式(如MVC、信号槽),避免重复造轮子。
  2. 从简单设计开始,仅在必要时引入模式(如复杂度增加、需求变更频繁)。
  3. 结合UML图设计架构,确保模式的合理应用,避免过度设计。

文章转载自:
http://anelasticity.bdypl.cn
http://cephalic.bdypl.cn
http://acumen.bdypl.cn
http://airsick.bdypl.cn
http://auberge.bdypl.cn
http://ailurophobia.bdypl.cn
http://amboceptor.bdypl.cn
http://bromine.bdypl.cn
http://carnification.bdypl.cn
http://brigatisti.bdypl.cn
http://apophyllite.bdypl.cn
http://bebeeru.bdypl.cn
http://christocentrism.bdypl.cn
http://besides.bdypl.cn
http://awakening.bdypl.cn
http://cementation.bdypl.cn
http://benzoin.bdypl.cn
http://campanero.bdypl.cn
http://cardcase.bdypl.cn
http://accumulative.bdypl.cn
http://bajada.bdypl.cn
http://amianthus.bdypl.cn
http://arriviste.bdypl.cn
http://bladderwort.bdypl.cn
http://actualism.bdypl.cn
http://accomodate.bdypl.cn
http://camerlengo.bdypl.cn
http://calicut.bdypl.cn
http://caulocaline.bdypl.cn
http://baboon.bdypl.cn
http://www.dtcms.com/a/281658.html

相关文章:

  • Docker 镜像推送至 Coding 制品仓库超时问题排查与解决
  • 业务分析业务架构视角
  • 软件测试面试经历分享?
  • 在 SymPy 中精确提取三角函数系数的深度分析
  • LLM面试题目 3
  • 项目进度与预算脱节,如何进行同步管理
  • Linux部署Redis
  • 46. 携带研究材料(01背包二维数组)
  • Java程序员学从0学AI(五)
  • 发票查验接口的计费规则-核验成功返回参数
  • SpringBoot集成RocketMQ的两种方式
  • WGAS+WGCNA分析文章套路
  • LeetCode Hot100 【1.两数之和、2.两数相加、3.无重复字符的最长子串】
  • 动态数组:ArrayList的实现原理
  • 504网关超时可能是哪些原因导致?
  • web前端渡一大师课 01 事件循环
  • 【交流等效负载电阻的推导】
  • SpringBoot 项目搭建的 4 种常用方式,从入门到实践
  • 魔力宝贝归来虚拟机版怎么修复卡第一个任务
  • Kimi K2驱动Claude Code,稳定且低价
  • 入选《机器视觉》:视觉AI 生态链加速工业检测场景落地
  • MySQL数据库----函数
  • vue3:wangEditor使用过程中,点击编辑回显数据的问题修复.
  • 操作HTML网页的知识点
  • 飞搭系列 | 子事件流节点,让逻辑复用更简单!
  • 【前端】Vue 3 页面开发标准框架解析:基于实战案例的完整指南
  • 第二次线上事故
  • 【leetcode】263.丑数
  • Unity 多人游戏框架学习系列一
  • (附源码)基于 Go 和 gopacket+Fyne 的跨平台网络抓包工具开发实录