【C++類和數據抽象】消息處理示例(1):從設計模式到實戰應用

目錄

一、數據抽象概述

二、消息處理的核心概念

2.1 什么是消息處理?

2.2 消息處理的核心目標

三、基于設計模式的消息處理實現

3.1 觀察者模式(Observer Pattern)

3.2 命令模式(Command Pattern)

四、實戰場景:GUI 框架中的消息處理

4.1 模擬 Qt 信號槽機制

五、高級主題:多線程消息隊列

5.1 基于隊列的異步消息處理

六、消息處理的最佳實踐

6.1 解耦優先

6.2 線程安全

6.3 錯誤處理

6.4 性能優化

七、總結


在 C++ 的復雜系統開發中,消息處理是實現組件解耦、異步通信和事件驅動的核心機制。無論是 GUI 框架中的按鈕點擊響應,還是分布式系統中的模塊通信,消息處理都扮演著關鍵角色。本文將圍繞設計模式(如觀察者模式、命令模式)和實戰場景(如 GUI 事件、多模塊通信),深入探討 C++ 中消息處理的實現方式。

一、數據抽象概述

數據抽象是一種編程技術,它允許我們定義數據類型,同時隱藏其內部實現細節。意味著,我們只需關注數據對象能做什么,而不是它們是如何做的。在C++中,數據抽象主要通過類和對象實現。類定義了數據成員和成員函數,其中數據成員用于存儲數據,而成員函數用于操作這些數據。通過將數據成員設置為私有(private),確保了它們只能通過類的公共接口(public成員函數)訪問。

數據抽象具有多個優點:

  • 安全性:數據抽象可以防止不恰當的數據訪問,從而保護數據的安全性。
  • 簡化復雜性:允許我們處理復雜系統時,只關注其高層次的抽象,而不是底層細節。
  • 易于維護和修改:由于實現細節被隱藏,修改內部實現時不會影響到使用這些數據的其他部分。
  • 可重用性:抽象數據類型可以被重復使用,從而提高代碼的可重用性。

二、消息處理的核心概念

2.1 什么是消息處理?

消息是組件間傳遞的信息載體,包含事件類型、數據參數等內容。
消息處理指接收消息并執行相應邏輯的過程,通常涉及:

  • 消息發送者:產生消息的組件(如按鈕點擊、傳感器數據更新)。
  • 消息接收者:處理消息的組件(如事件處理器、業務邏輯模塊)。
  • 消息通道:連接發送者與接收者的通信鏈路(如函數調用、隊列、信號槽)。

2.2 消息處理的核心目標

  • 解耦組件:發送者與接收者無需直接依賴,提高系統靈活性。
  • 異步通信:支持非阻塞消息傳遞,提升系統響應速度。
  • 可擴展性:方便添加新的消息類型或處理邏輯。

三、基于設計模式的消息處理實現

3.1 觀察者模式(Observer Pattern)

①模式原理

  • 角色
    • 主題(Subject):維護觀察者列表,發送消息。
    • 觀察者(Observer):接收消息并執行處理邏輯。
  • 核心機制:主題與觀察者通過抽象接口解耦,主題發送消息時自動通知所有注冊的觀察者。

②代碼示例:按鈕點擊事件處理

#include <iostream>
#include <vector>
#include <memory>
#include <algorithm> // 使用 std::remove_if// 抽象觀察者接口
class ButtonObserver {
public:// 純虛函數,具體觀察者需要實現該函數來處理按鈕點擊事件virtual void OnButtonClick() = 0;// 虛析構函數,確保在通過基類指針刪除派生類對象時能正確調用派生類的析構函數virtual ~ButtonObserver() = default;
};// 具體觀察者:日志記錄器
class LogObserver : public ButtonObserver {
public:// 實現 OnButtonClick 函數,處理日志記錄void OnButtonClick() override {std::cout << "Button clicked: Logging event..." << std::endl;}
};// 具體觀察者:業務處理器
class BusinessObserver : public ButtonObserver {
public:// 實現 OnButtonClick 函數,處理業務邏輯void OnButtonClick() override {std::cout << "Button clicked: Processing business logic..." << std::endl;}
};// 主題:按鈕類
class Button {
public:// 向觀察者列表中添加觀察者void AddObserver(std::shared_ptr<ButtonObserver> observer) {if (observer) {observers_.push_back(observer);} else {std::cerr << "Error: Attempt to add a null observer." << std::endl;}}// 從觀察者列表中移除指定的觀察者void RemoveObserver(std::shared_ptr<ButtonObserver> observer) {if (observer) {auto newEnd = std::remove_if(observers_.begin(), observers_.end(), [&observer](const std::shared_ptr<ButtonObserver>& obs) {return obs == observer;});if (newEnd != observers_.end()) {observers_.erase(newEnd, observers_.end());} else {std::cerr << "Error: Observer not found in the list." << std::endl;}} else {std::cerr << "Error: Attempt to remove a null observer." << std::endl;}}// 模擬按鈕點擊,發送消息給所有注冊的觀察者void Click() {std::cout << "Button clicked: Notifying observers..." << std::endl;for (const auto& observer : observers_) {if (observer) {observer->OnButtonClick();} else {std::cerr << "Error: Found a null observer in the list." << std::endl;}}}private:// 存儲觀察者的列表std::vector<std::shared_ptr<ButtonObserver>> observers_;
};// 主函數:測試消息處理流程
int main() {Button button;auto logObserver = std::make_shared<LogObserver>();auto businessObserver = std::make_shared<BusinessObserver>();button.AddObserver(logObserver);button.AddObserver(businessObserver);button.Click(); // 觸發消息發送return 0;
}

3.2 命令模式(Command Pattern)

①模式原理

  • 角色
    • 命令(Command):封裝消息內容和處理邏輯。
    • 調用者(Invoker):觸發命令執行。
    • 接收者(Receiver):實際執行命令的組件。
  • 核心機制:將 “消息” 封裝為命令對象,支持動態添加、撤銷命令,實現異步消息處理。

②代碼示例:文件操作命令隊列

#include <iostream>
#include <vector>
#include <memory>// 抽象命令接口
class FileCommand {
public:virtual void Execute() = 0;virtual ~FileCommand() = default;
};// 具體命令:創建文件
class CreateFileCommand : public FileCommand {
public:CreateFileCommand(const std::string& filename) : filename_(filename) {}void Execute() override {std::cout << "Creating file: " << filename_ << std::endl;// 實際文件創建邏輯}private:std::string filename_;
};// 具體命令:刪除文件
class DeleteFileCommand : public FileCommand {
public:DeleteFileCommand(const std::string& filename) : filename_(filename) {}void Execute() override {std::cout << "Deleting file: " << filename_ << std::endl;// 實際文件刪除邏輯}private:std::string filename_;
};// 命令調用者:消息隊列
class CommandQueue {
public:void AddCommand(std::shared_ptr<FileCommand> command) {commands_.push_back(command);}void ProcessCommands() { // 批量處理消息for (const auto& command : commands_) {command->Execute();}commands_.clear();}private:std::vector<std::shared_ptr<FileCommand>> commands_;
};// 主函數:測試命令模式
int main() {CommandQueue queue;queue.AddCommand(std::make_shared<CreateFileCommand>("data.txt"));queue.AddCommand(std::make_shared<DeleteFileCommand>("temp.txt"));std::cout << "Processing commands..." << std::endl;queue.ProcessCommands();return 0;
}

四、實戰場景:GUI 框架中的消息處理

4.1 模擬 Qt 信號槽機制

Qt 的信號槽機制是 C++ 中消息處理的經典實現,通過元對象系統實現組件間解耦。以下是簡化的模擬實現:

①信號槽核心類

#include <iostream>
#include <vector>
#include <functional>// 信號類:支持綁定槽函數
template <typename... Args>
class Signal {
public:void Connect(std::function<void(Args...)> slot) {slots_.push_back(slot);}void Emit(Args... args) { // 發送消息for (const auto& slot : slots_) {slot(args...);}}private:std::vector<std::function<void(Args...)>> slots_;
};// 按鈕類:發送點擊消息
class GuiButton {
public:Signal<> clicked; // 無參數信號
};// 主函數:模擬GUI消息處理
int main() {GuiButton button;// 綁定槽函數:日志輸出button.clicked.Connect([]() {std::cout << "Button clicked (via signal-slot)!" << std::endl;});// 觸發信號:模擬按鈕點擊std::cout << "Simulating button click..." << std::endl;button.clicked.Emit();return 0;
}

五、高級主題:多線程消息隊列

5.1 基于隊列的異步消息處理

在多線程場景中,消息隊列是實現線程間通信的常用方式。以下是一個簡單的線程安全消息隊列實現:

①線程安全隊列類

#include <iostream>
#include <queue>template <typename T>
class NonThreadSafeQueue {
public:void Enqueue(T message) {queue_.push(std::move(message));}T Dequeue() {T message = queue_.front();queue_.pop();return message;}bool Empty() {return queue_.empty();}private:std::queue<T> queue_;
};// 消息類型定義
struct Message {int type;std::string data;
};// 生產者線程(非線程安全,僅演示邏輯)
void Producer(NonThreadSafeQueue<Message>& queue) {Message msg = {1, "Hello, message queue!"};queue.Enqueue(msg);std::cout << "Producer sent message: " << msg.data << std::endl;
}// 消費者線程(非線程安全,僅演示邏輯)
void Consumer(NonThreadSafeQueue<Message>& queue) {while (!queue.Empty()) {Message msg = queue.Dequeue();std::cout << "Consumer received message: " << msg.data << std::endl;}
}int main() {NonThreadSafeQueue<Message> queue;Producer(queue);Consumer(queue);return 0;
}

六、消息處理的最佳實踐

6.1 解耦優先

  • 使用抽象接口(如觀察者模式中的ButtonObserver)隔離發送者與接收者。
  • 避免硬編碼依賴,通過工廠模式或依賴注入創建消息處理器。

6.2 線程安全

  • 多線程環境中,對共享消息隊列加鎖(如std::mutex)或使用無鎖隊列。
  • 消息對象設計為不可變或線程安全,避免競態條件。

6.3 錯誤處理

為消息處理函數添加異常捕獲,避免未處理異常導致程序崩潰。?

void OnButtonClick() {try {// 消息處理邏輯} catch (const std::exception& e) {std::cerr << "Message handling error: " << e.what() << std::endl;}
}

6.4 性能優化

  • 批量處理消息(如命令模式中的ProcessCommands())減少函數調用開銷。
  • 使用智能指針(如std::shared_ptr)管理消息對象,避免內存泄漏。

七、總結

模式 / 場景核心機制適用場景
觀察者模式主題 - 觀察者訂閱關系GUI 事件、狀態變更通知
命令模式消息封裝為可執行對象撤銷操作、異步任務隊列
信號槽機制動態綁定消息處理器Qt 等 GUI 框架
多線程隊列線程安全的消息傳遞通道跨線程通信、異步任務處理

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/81031.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81031.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81031.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【統計方法】交叉驗證:Resampling, nested 交叉驗證等策略 【含R語言】

Resampling (重采樣方法) 重采樣方法是從訓練數據中反復抽取樣本&#xff0c;并在每個&#xff08;重新&#xff09;樣本上重新調整模型&#xff0c;以獲得關于擬合模型的附加信息的技術。 兩種主要的重采樣方法 Cross-Validation (CV) 交叉驗證 &#xff1a; 用于估計測試誤…

常見的 CSS 知識點整理

1. 盒模型&#xff08;Box Model&#xff09;是什么&#xff1f;標準盒模型和 IE 盒模型的區別&#xff1f; 答案&#xff1a; CSS 盒模型將元素視為一個盒子&#xff0c;由內容&#xff08;content&#xff09;、內邊距&#xff08;padding&#xff09;、邊框&#xff08;bor…

Educational Codeforces Round 178 div2(題解ABCDE)

A. Three Decks #1.由于最后三個數會相等&#xff0c;提前算出來和&#xff0c;%3判斷&#xff0c;再判前兩個數是否大于 #include<iostream> #include<vector> #include<stdio.h> #include<map> #include<string> #include<algorithm> #…

如何創建一個導入模板?全流程圖文解析

先去找到系統內可以上傳東西的按鈕 把你的模板上傳上去,找到對應的fileName 圖里的文字寫錯了,是復制粘貼"filePath"到URL才能下載

通信原理第七版與第六版區別附pdf

介紹 我用夸克網盤分享了「通信原理 第7版》樊昌信」&#xff0c;鏈接&#xff1a;https://pan.quark.cn/s/be7c5af4cdce 《通信原理&#xff08;第7版&#xff09;》是在第6版的基礎上&#xff0c;為了適應當前通信技術發展和教學需求&#xff0c;并吸取了數十所院校教師的反…

Mysql唯一性約束

唯一性約束&#xff08;Unique Constraint&#xff09;是數據庫設計中用于保證表中某一列或多列組合的值具有唯一性的一種規則。它可以防止在指定列中插入重復的數據&#xff0c;有助于維護數據的完整性和準確性。下面從幾個方面為你詳細解釋 作用 確保數據準確性&#xff1a…

測試基礎筆記第十六天

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 一、UI自動化介紹1.認識UI自動化測試2.實施UI自動化測試前置條件3.UI自動化測試執行時機4.UI自動化測試核心作用和劣勢 二、認識Web自動化測試工具-Selenium021.Sel…

PaddleX的安裝

參考&#xff1a;安裝PaddlePaddle - PaddleX 文檔 1、安裝PaddlePaddle 查看 docker 版本 docker --version 若您通過 Docker 安裝&#xff0c;請參考下述命令&#xff0c;使用飛槳框架官方 Docker 鏡像&#xff0c;創建一個名為 paddlex 的容器&#xff0c;并將當前工作目…

長效住宅IP是什么?如何獲取長效住宅IP?

在當今的互聯網世界里&#xff0c;IP地址作為連接用戶與網站之間的橋梁&#xff0c;其重要性不言而喻。對于跨境電商、社交媒體運營以及數據采集等領域的專業人士而言&#xff0c;普通的IP地址已無法滿足日益復雜的需求。他們更需要一種穩定、安全且持久的長效住宅IP來完成各類…

02 業務流程架構

業務流程架構提供了自上而下的組織鳥瞰圖&#xff0c;是業務流程的全景圖。根據所采用的方法不同&#xff0c;有時被稱為流程全景圖或高層級流程圖&#xff0c;提供了業務運營中所有業務流程的整體視圖。 這樣有助于理解企業內部各個業務流程之間的相互關系以及它們如何共同工…

jenkins slave節點打包報錯Failed to create a temp file on

jenkins slave節點打包報錯 一、報錯信息 FATAL: Unable to produce a script file Also: hudson.remoting.Channel$CallSiteStackTrace: Remote call to slave-83at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1784)at hudson.remoting.UserRequest$…

什么是 Swagger 以及如何在 Spring Boot 中實現 Swagger:配置與實踐指南

在現代 RESTful API 開發中&#xff0c;Swagger 是一種廣泛使用的工具&#xff0c;用于生成、描述和可視化 API 文檔。它極大地簡化了 API 的開發、測試和維護過程。結合 Spring Boot&#xff0c;Swagger 可以快速集成到項目中&#xff0c;生成交互式 API 文檔&#xff0c;方便…

Xilinx FPGA支持的FLASH型號匯總

以博主這些年的FPGA開發使用經驗來看&#xff0c;FPGA開發的主流還是以Xilinx FPGA為主&#xff0c;貿易戰關稅戰打了這么多年&#xff0c;我們做研發的也不可避免的要涉及一些國產替代的工作&#xff1b;這里把Xilinx FPGA官方支持的各類&#xff08;國產和非國產&#xff09;…

第3講:ggplot2完美入門與美化細節打磨——從基礎繪制到專業級潤色

目錄 1. 為什么選擇ggplot2? 2. 快速了解ggplot2繪圖核心邏輯 3. 基礎繪圖示范:柱狀圖、折線圖、散點圖 (1)簡單柱狀圖 (2)折線圖示范 (3)高級散點圖 + 擬合線 4. 精細美化:細節打磨決定專業感 5. 推薦的美化小插件(可選進階) 6. 小練習:快速上手一幅美化…

Vue3 上傳后的文件智能預覽(實戰體會)

目錄 前言1. Demo12. Demo2 前言 &#x1f91f; 找工作&#xff0c;來萬碼優才&#xff1a;&#x1f449; #小程序://萬碼優才/r6rqmzDaXpYkJZF 爬蟲神器&#xff0c;無代碼爬取&#xff0c;就來&#xff1a;bright.cn 此處的基本知識涉及較少&#xff0c;主要以Demo的形式供大…

transformer-實現單層Decoder 層

Decoder Layer 論文地址 https://arxiv.org/pdf/1706.03762 解碼器層結構 Transformer解碼器層由三種核心組件構成&#xff1a; Masked多頭自注意力&#xff1a;關注解碼器序列當前位置之前的上下文&#xff08;因果掩碼&#xff09; Encoder-Decoder多頭注意力&#xff1a;關…

設計模式每日硬核訓練 Day 16:責任鏈模式(Chain of Responsibility Pattern)完整講解與實戰應用

&#x1f504; 回顧 Day 15&#xff1a;享元模式小結 在 Day 15 中&#xff0c;我們學習了享元模式&#xff08;Flyweight Pattern&#xff09;&#xff1a; 通過共享對象&#xff0c;分離內部狀態與外部狀態&#xff0c;大量減少內存開銷。適用于字符渲染、游戲場景、圖標緩…

大數據開發環境的安裝,配置(Hadoop)

1. 三臺linux服務器的安裝 1. 安裝VMware VMware虛擬機軟件是一個“虛擬PC”軟件&#xff0c;它使你可以在一臺機器上同時運行二個或更多Windows、DOS、LINUX系統。與“多啟動”系統相比&#xff0c;VMWare采用了完全不同的概念。 我們可以通過VMware來安裝我們的linux虛擬機…

多模態大語言模型arxiv論文略讀(四十九)

When Do We Not Need Larger Vision Models? ?? 論文標題&#xff1a;When Do We Not Need Larger Vision Models? ?? 論文作者&#xff1a;Baifeng Shi, Ziyang Wu, Maolin Mao, Xin Wang, Trevor Darrell ?? 研究機構: UC Berkeley、Microsoft Research ?? 問題背…

【深度學習與大模型基礎】第14章-分類任務與經典分類算法

Part 1&#xff1a;什么是分類任務&#xff1f; 1.1 分類就是“貼標簽” 想象你有一堆水果&#xff0c;有蘋果&#x1f34e;、橘子&#x1f34a;、香蕉&#x1f34c;&#xff0c;你的任務是讓機器學會自動判斷一個新水果屬于哪一類——這就是分類&#xff08;Classification&…