【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
英文地址,請注明出處:http://en.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類&…