【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://www.pswp.cn/diannao/91221.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91221.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【HarmonyOS】ArkUI-X 跨平台框架入门详解(一)

【HarmonyOS】ArkUI-X 跨平台框架入门详解&#xff08;一&#xff09; 一、前言 1、ArkUI-X框架是什么&#xff1f; ArkUI-X是在ArkUI开发框架的基础上&#xff0c;进行扩展。支持多个OS平台&#xff0c;目前支持OpenHarmony、HarmonyOS、Android、 iOS。2、ArkUI-X目前的能力现…

开发者进化论:驾驭AI,开启软件工程新纪元

导语&#xff1a;人工智能&#xff08;AI&#xff09;的浪潮&#xff0c;特别是以大型语言模型&#xff08;LLM&#xff09;为代表的生成式AI&#xff0c;正以前所未有的力量&#xff0c;深刻地重塑着软件开发的传统疆域。我们正处在一个关键的转折点——产业的重心正从模型的“…

智慧水务平台,智慧水务,惠及民生,提升水务管理效率与服务质量

平升电子智慧水务平台支持海量物联网数据接入实现供水全流程信息化&#xff0c;深度逻辑运算自动控制实现供水调度智慧化&#xff0c;融入管网地理信息系统实现测点数据时空化&#xff0c;数字孪生实现水厂各工艺环节运行情况可视化&#xff0c;多角度统计分析实现水务运营管理…

【Unity基础】Unity中元素的层级排序

在Unity中&#xff0c;控制元素的层级排序&#xff08;渲染顺序&#xff09;是确保场景正确显示的关键。以下是常见的层级排序方式及其适用场景&#xff1a;1. 通过GameObject的层级顺序&#xff08;Sorting Layer/Order in Layer&#xff09; 适用对象&#xff1a;2D精灵&…

梁的振动特征函数分析2

问题7&#xff1a;左端固定、右端自由梁的振动分析 考虑梁的振动方程&#xff1a; uttKuxxxx0,0<x<l,K>0 u_{tt} K u_{xxxx} 0, \quad 0 < x < l, \quad K > 0 utt​Kuxxxx​0,0<x<l,K>0 边界条件&#xff1a; 左端固定&#xff08;位移和斜率为零…

AI问答-Token:在人工智能领域,Token 是模型处理文本的核心单元 / 最小可处理片段

一、在人工智能领域&#xff0c;Token 是模型处理文本的核心单元&#xff0c;可理解为文本的“最小可处理片段”二、表格理解类别详细说明基本定义Token 是模型处理文本的最小语义或语法单位&#xff0c;可以是单词、子词、字符、标点符号或特殊符号。例如&#xff1a;- 单词级…

读取ubuntu的磁盘分区表与超级块

1.读取磁盘分区表sudo fdisk -l /dev/sda2.计算偏移量分区起始偏移 4096 512 2097152 字节 超级块位置 2097152 1024 2098176字节3.快速验证&#xff08;直接检查魔数 53 &#xff09;# 检查偏移 2,098,176 处是否有 EXT4 魔数 sudo dd if/dev/sda bs1 count2 skip$((209…

科技驯服烈日狂沙:中东沙漠农场的光储革命

作者 | 小葳 阿布扎比郊外的午后&#xff0c;沙漠灼热、干旱难耐。 然而一座农场内&#xff0c;景象截然不同&#xff1a;蔬菜生机盎然&#xff0c;果实挂满枝头。农户轻点手机&#xff0c;远程调控着大棚内温湿度&#xff1b;灌溉与施肥&#xff0c;则由系统自动精准执行。 这…

基于Chinese-CLIP与ChromaDB的中文图像检索功能实现

本文按“原理 → 代码 → 讲解”三层展开&#xff0c;读者只需具备 Python 基础即可跟随完成一个可落地的以文搜图应用。 一、整体思路 把图片和文字都转成固定长度的向量&#xff08;768 维&#xff09;。把图片向量提前存入向量数据库。查询时把文字转成向量&#xff0c;再找…

Pandas 的 Index 与 SQL Index 的对比

一、Pandas 的 Index&#xff08;索引&#xff09;是什么&#xff1f;Pandas 的 Index 就像是 Excel 表格的行号 列标题&#xff0c;或者书的目录。核心作用&#xff1a;定位数据&#xff1a;就像 Excel 中用行号和列名定位单元格&#xff08;如 A1、B2&#xff09;&#xff0…

Rust指针选择

Rust指针选择&#xff1a; 1.优先使用引用&#xff1a;安全访问数据 fn process(data: &[i32]) { /* ... */ }2.需要所有权转移时用 Box fn create() -> Box<Data> { Box::new(Data::new()) }3.共享数据用 Rc/Arc // 单线程 let shared Rc::new(data);// 多线程 …

【实用IP查询工具】IP数据云-IP地址查询离线库使用方案

IP数据云&#xff08;ipdatacloud.com&#xff09;深耕IP地址查询技术&#xff0c;打造了覆盖多场景、高精度的IP地址查询离线库&#xff0c;为不同行业客户提供稳定、高效的本地化数据支持。 什么是IP 地址查询 离线库&#xff1f; IP地址查询离线库是将海量IP地址与对应的地…

UE5CameraShake参数详解

使用CameraShakeBase蓝图中简单调用和调试 使用 Play World Camera Shake 这个节点带有震动衰减效果Epicenter是震动中心点 传入Boss的位置 Inner Radius是 内部范围 距离小于内部范围时 , 全强度震动Outer Radius是 外部范围 距离大于外部范围时 , 就无震动Falloff 是衰…

java学习 day4 分布式锁

P60分布式锁误删线程标示和锁中标示一致P61分布式锁的原子性问题判断锁标示和释放锁不同时 造成误删P62Lua脚本P63java执行Lua脚本原子性P64redissionredisson框架P65redisson入门P66redisson可重入锁原理和测试redisson可重入锁P67锁重试看门狗看到67 10min处&#xff0c;看不…

python+selenium UI自动化初探

在公司上班闲的没事干&#xff0c;学点selenium 先安装selenium pip install selenium出现报错 Cannot uninstall certifi None ╰─> The packages contents are unknown: no RECORD file was found for certifi.hint: You might be able to recover from this via: pip in…

前端-CSS-day3

目录 1、结构伪类选择器-基本使用 2、结构伪类选择器-公式用法 3、伪元素选择器 4、盒子模型-组成 5、盒子模型-边框线 6、盒子模型-单方向边框线 7、盒子模型-内边距 8、盒子模型-内边距-多值写法 9、盒子模型-尺寸计算 10、盒子模型-版心居中 11、清除默认样式 1…

BPE(Byte Pair Encoding)分词算法

下面是对 BPE&#xff08;Byte Pair Encoding&#xff09;分词算法的深入介绍&#xff0c;涵盖其背景、原理、实现细节、数学机制、优缺点以及在自然语言处理中的实际应用。一、背景与动机在自然语言处理中&#xff0c;模型输入通常需要被转换为数值序列&#xff0c;而这首先需…

ssm学习笔记day07mybatis

项目的准备 创建springboot项目&#xff08;moudle&#xff09;&#xff0c;加入依赖lombok(自动添加setter,getter,toString)、Spring Web&#xff08;处理servlet请求&#xff09;、MySQL Driver(mysql的驱动器&#xff09;、JDBC&#xff08;JAVA与mysql的接口&#xff09;、…

Kubernetes 高级调度01

目录 一、 初始化容器 InitContainer 1. InitContainer 的基本概念 2. 延迟指定时间后启动 3. 使用初始化容器修改内核参数 4. 等待依赖的服务启动后再启动应用 5. pause 容器 二、 临时容器 Ephemeral Containers 1. 临时容器的概念 2. 临时容器的使用示例 三、 自动…

Spring MVC2

在Spring MVC1中&#xff0c;我们知道了MVC的定义&#xff0c;同时也知道了RequestMapping和RestController这个注解的作用。本篇文章&#xff0c;我们将学习使用Spring MVC获取请求参数和返回不同的响应等等请求传递单个参数如图所示&#xff0c;创建RequestController类&…