設計模式 Day 5:夯實觀察者模式(Boost 實戰精講)

今天我們繼續深入觀察者模式的學習,不再局限于手寫的抽象結構,而是聚焦于真實項目中如何使用成熟框架(如 Boost.Signals2)高效落地觀察者模式

本篇采用**“理論解析 + 問答講解 + 實戰用例”**結構,幫助你從設計思想到工程實現,系統理解觀察者模式,并掌握在職場中如何高質量表達。


一、觀察者模式的核心理論

📌 定義(來自《設計模式》GoF):

**觀察者模式(Observer Pattern)**定義對象之間的一對多依賴關系,使得當一個對象狀態發生變化時,所有依賴于它的對象都會被自動通知和更新。

? 模式動機:

  • 某個對象(Subject)狀態改變后,多個依賴對象(Observers)需要自動獲取更新。
  • 為避免強耦合與重復代碼,采用抽象接口進行解耦。

🧱 角色劃分:

角色職責
Subject維護觀察者列表,狀態變更時通知所有觀察者
Observer定義一個更新接口,供主題調用
ConcreteX實現具體主題/觀察者邏輯

🔁 通知流程:

  主題狀態變化  →  遍歷觀察者列表  →  調用每個 observer 的 update() 方法

在這里插入圖片描述

? 應用特征:

  • 主題變化 → 觀察者自動聯動
  • 低耦合、高擴展性
  • 一對多廣播結構,面向事件的典型模型

二、Q1:為什么不能一直手寫觀察者模式?

? 答案:
雖然觀察者結構很清晰,但在實際項目中手寫版本存在如下問題:

問題影響
增刪觀察者需手動管理易導致懸空指針、內存泄漏
缺乏線程安全多線程場景下容易數據競爭
生命周期管理復雜觀察者被銷毀后,主題還在通知 → 崩潰
使用語法繁瑣不夠直觀、不易復用

因此在工程中,我們推薦使用成熟庫:

  • ? boost::signals2
  • ? Qt signal/slot
  • ? RxCpp

三、Q2:Boost.Signals2 的核心邏輯框架是怎樣的?

? 答案:Boost.Signals2 提供了“信號(signal)與槽(slot)”機制,等價于觀察者結構:

  • signal = Subject(可連接多個觀察者)
  • slot = Observer(綁定的響應函數)

🎯 流程圖:

signal<T>::connect(slot函數) → 存儲函數指針
→ signal(...) 觸發 → 調用所有 slot

? 優勢機制:

  • 自動解綁:生命周期綁定,防止懸空引用
  • 支持多種 slot 類型:函數指針、lambda、成員函數等
  • 默認線程安全(基于 mutex)
  • 返回值合并器(collectors)

四、Q3:如何用 Boost.Signals2 快速實現“股票通知系統”?

📌 場景:

多個模塊訂閱價格更新事件,無需關心數據來源。

? 實戰代碼:

#include <iostream>
#include <boost/signals2.hpp>boost::signals2::signal<void(const std::string&, float)> priceChanged;void traderA(const std::string& symbol, float price) {std::cout << "[TraderA] " << symbol << ": " << price << " 元" << std::endl;
}class TraderB {
public:void onPrice(const std::string& symbol, float price) {std::cout << "[TraderB] " << symbol << ": " << price << " 元" << std::endl;}
};int main() {priceChanged.connect(&traderA);TraderB b;priceChanged.connect(boost::bind(&TraderB::onPrice, &b, _1, _2));priceChanged("TSLA", 888.8);priceChanged("AAPL", 175.3);return 0;
}

? 輸出:

[TraderA] TSLA: 888.8 元
[TraderB] TSLA: 888.8 元
[TraderA] AAPL: 175.3 元
[TraderB] AAPL: 175.3 元

五、Q4:Boost 如何自動解綁觀察者?如何避免懸空?

? 答案:Boost 提供兩種方式:

? 方法一:使用 scoped_connection 自動斷連

boost::signals2::scoped_connection conn = signal.connect(...);
// 當 conn 離開作用域,自動斷開連接

? 方法二:用 shared_ptr 綁定觀察者對象

std::shared_ptr<TraderB> p = std::make_shared<TraderB>();
signal.connect(boost::bind(&TraderB::onPrice, p, _1, _2));
// 當 p 被釋放,觀察者自動無效,不再調用

這解決了傳統觀察者最大的問題之一:“對象被釋放但主題還在通知”


六、Q5:常見工程落地場景(強記)

實戰場景描述
股票/證券系統客戶端訂閱行情變化 → 推送更新
硬件溫度采集系統溫控模塊、報警模塊訂閱傳感器數據
插件機制插件監聽核心狀態或生命周期事件
UI 數據綁定界面組件監聽模型變化 → 實時刷新顯示
日志 hook 管理注冊多個模塊日志輸出監聽,分類處理
游戲對象狀態廣播血量/坐標變化推送至渲染、AI、動畫模塊

這些實際場景中,Boost.Signals2 都是優秀的解耦工具。


七、Q6:面試場景問“你用過觀察者模式嗎?”怎么答最加分?

? 標準回答范式:

“我在多個項目中用過觀察者模式實現事件解耦,特別是在實時推送系統中使用 Boost.Signals2 實現了模塊間的消息廣播。相比手寫觀察者,Boost 提供了線程安全、自動解綁、連接管理的完整機制,比如我們用 scoped_connection 來綁定每個 UI 組件,避免對象銷毀時崩潰。”

? 加分:結合“具體場景 + 技術細節 + 優劣對比”,突出實戰經驗。


八、總結記憶

觀察者模式是設計模式中應用最廣、最接地氣的一種。

🎯 理解關鍵詞:

  • 一對多、松耦合、自動通知、廣播機制
  • Boost.Signals2 = 安全 + 簡潔 + 模塊化

? 口訣記憶:

“狀態一變多方知,信號插槽最優解;解綁安全避崩潰,實戰面試皆拿捏。”


明日預告:策略模式(Strategy Pattern)實戰講解:支付/壓縮/路徑選擇等算法切換的優雅實現。

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

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

相關文章

設計模式 Day 3:抽象工廠模式(Abstract Factory Pattern)詳解

經過前兩天的學習&#xff0c;我們已經掌握了單例模式與工廠方法模式&#xff0c;理解了如何控制實例個數與如何通過子類封裝對象的創建邏輯。 今天&#xff0c;我們將進一步深入“工廠”體系&#xff0c;學習抽象工廠模式&#xff08;Abstract Factory Pattern&#xff09;&a…

MySQL:事務的理解

一、CURD不加控制&#xff0c;會有什么問題 &#xff08;1&#xff09;因為&#xff0c;MySQL里面存的是數據&#xff0c;所以很有可能會被多個客戶訪問&#xff0c;所以mysqld可能一次會接受到多個關于CURD的請求。&#xff08;2&#xff09;且mysql內部是采用多線程來完成數…

藍橋杯刷題--寶石組合

在一個神秘的森林里&#xff0c;住著一個小精靈名叫小藍。有一天&#xff0c;他偶然發現了一個隱藏在樹洞里的寶藏&#xff0c;里面裝滿了閃爍著美麗光芒的寶石。這些寶石都有著不同的顏色和形狀&#xff0c;但最引人注目的是它們各自獨特的 “閃亮度” 屬性。每顆寶石都有一個…

DAY06:【pytorch】圖像增強

1、基本概念 數據增強&#xff0c;又稱數據增廣、數據擴增&#xff0c;是對訓練集進行變換&#xff0c;使訓練集更豐富&#xff0c;從而讓模型更具泛化能力 2、裁剪 — — Crop 2.1 transforms.CenterCrop 功能&#xff1a;從圖像中心裁剪圖片 size&#xff1a;所需裁剪圖…

mysql 禁止 讀 某個 表

mysql 禁止 讀 某個 表 mysql禁用某張表,禁用MySQL表的操作 https://shuyeidc.com/wp/89479.html MySQL嚴格禁止讀取表如何避免數據泄露 https://www.kdun.cn/ask/394700.html select host,user from mysql.user; FLUSH PRIVILEGES; 1. MySQL嚴格禁止讀取表如何避免數據泄露…

機器學習 從入門到精通 day_03

1. KNN算法-分類 1.1 樣本距離判斷 明可夫斯基距離&#xff1a;歐式距離&#xff0c;明可夫斯基距離的特殊情況&#xff1b;曼哈頓距離&#xff0c;明可夫斯基距離的特殊情況。 兩個樣本的距離公式可以通過如下公式進行計算&#xff0c;又稱為歐式距離。 &#xff08;…

LeetCode 熱題 100_零錢兌換(85_322_中等_C++)(動態規劃)

LeetCode 熱題 100_零錢兌換&#xff08;85_322&#xff09; 題目描述&#xff1a;輸入輸出樣例&#xff1a;題解&#xff1a;解題思路&#xff1a;思路一&#xff08;動態規劃&#xff09;&#xff1a; 代碼實現代碼實現&#xff08;思路一&#xff08;動態規劃&#xff09;&a…

游戲盾IP可以被破解嗎

游戲盾IP&#xff08;如上海云盾SDK、騰訊云游戲盾&#xff09;是專為游戲行業設計的高防服務&#xff0c;旨在抵御DDoS攻擊、CC攻擊等威脅。其安全性取決于??技術架構、防護能力??以及??運維策略??。雖然理論上沒有絕對“無法破解”的系統&#xff0c;但游戲盾IP在合理…

SpringBoot實戰1

SpringBoot實戰1 一、開發環境&#xff0c;環境搭建-----創建項目 通過傳統的Maven工程進行創建SpringBoot項目 &#xff08;1&#xff09;導入SpringBoot項目開發所需要的依賴 一個父依賴&#xff1a;&#xff08;工件ID為&#xff1a;spring-boot-starter-parent&#xf…

【軟考-高級】【信息系統項目管理師】【論文基礎】進度管理過程輸入輸出及工具技術的使用方法

定義 項目進度管理是為了保證項目按時完成&#xff0c;對項目中所需的各個過程進行管理的過程&#xff0c;包括規劃進度、定義活動、活動優先級排序、活動持續時間、制定進度計劃和控制進度。 管理基礎 制定進度計劃的一般步驟 選擇進度計劃方法&#xff08;如關鍵路徑法&a…

【Linux】之【Get】 chroot 環境下安裝deb包時 .postinst:行 9: 201 段錯誤 (核心已轉儲)ldconfig

背景 如題&#xff0c;在postinst文件中直接執行了ldconfig命令&#xff0c; chroot 環境下出錯&#xff0c;安裝失敗 分析 chroot 環境下不能用 ldconfig 和 systemctl 但是&#xff1a;如果環境是 chroot&#xff0c;系統有可能沒完整掛載 /proc、/dev、系統路徑&#xff…

【論文精讀與實現】EDC2-RAG:基于動態聚類的文檔壓縮方法提升檢索增強生成RAG性能

?? 向所有學習者致敬! “學習不是裝滿一桶水,而是點燃一把火。” —— 葉芝 我的博客主頁: https://lizheng.blog.csdn.net ?? 歡迎點擊加入AI人工智能社區! ?? 讓我們一起努力,共創AI未來! ?? 1. 論文核心思想 這篇由清華大學團隊提出的EDC-RAG框架,針對當前…

OSPF接口的網絡類型和不規則區域

網絡類型(數據鏈路層所使用的協議所構建的二層網絡類型) 1、MA --- 多點接入網絡 BMA --- 支持廣播的多點接入網絡 NBMA --- 不支持廣播的多點接入網絡 2、P2P --- 點到點網絡 以太網 --- 以太網最主要的特點是需要基于MAC地址進行物理尋址&#xff0c;主要是因為以太網接口所連…

HTTP代理:內容分發戰場上的「隱形指揮官」

目錄 一、技術本質&#xff1a;流量博弈中的「規則改寫者」 二、戰略價值&#xff1a;內容分發的「四維升級」 三、實戰案例&#xff1a;代理技術的「降維打擊」 四、未來進化&#xff1a;代理技術的「認知升級」 五、結語&#xff1a;代理技術的「戰略覺醒」 在數字內容爆…

(2)網絡學習之堡壘機

堡壘機和防火墻的區別&#xff1a; 1.功能定位 防火墻主要負責抵御外部攻擊&#xff0c;就像一道堅固的城墻&#xff0c;防止黑客進入內部網絡。堡壘機則專注于內部管理&#xff0c;監控和記錄運維人員的操作行為&#xff0c;確保內部網絡的安全。 2.部署位置與作用范圍 防…

minio命令行客戶端mc常見用法

安裝minio命令行客戶端mc https://min-io.cn/docs/minio/linux/reference/minio-mc-admin.html # Windows安裝minio命令行客戶端 choco install minio-client -y# Linux安裝mc客戶端 wget -c -P /usr/local/bin/ https://dl.min.io/client/mc/release/linux-amd64/mc # 賦予可…

idea調整控制臺日志顯示長度

概述 在調試時&#xff0c;idea控制臺顯示的日志有長度顯示&#xff0c;當顯示的日志太長時&#xff0c;后生成的日志會覆蓋掉之前生成的日志內容。想要調整長度就可以按以下方式進行設置。 設置方法 Settings -> Editor -> General -> Console -> Override con…

oracle em修復之路

很早以前寫的文章&#xff0c;再草稿中存放太久了&#xff0c;今天開始整理20年來工作體會&#xff0c;以后陸續發出&#xff0c;希望給大家提供小小的幫助。 去年做的項目使用的oracle數據庫&#xff0c;最近要看一下&#xff0c;啟動機器進入系統&#xff0c;出現無法加載數…

QT中怎么隱藏或顯示最大化、最小化、關閉按鈕

文章目錄 方法一&#xff1a;通過代碼動態設置1、隱藏最大化按鈕2、隱藏最小化按鈕3、隱藏關閉按鈕方法 1&#xff1a;移除 WindowCloseButtonHint方法 2&#xff1a;使用 Qt::CustomizeWindowHint 并手動控制按鈕 4、同時隱藏最大化和最小化按鈕5、同時隱藏最大化和關閉按鈕6、…

性能比拼: Redis vs Memcached

本內容是對知名性能評測博主 Anton Putra Redis vs Memcached Performance Benchmark 內容的翻譯與整理, 有適當刪減, 相關指標和結論以原作為準 在本視頻中&#xff0c;我們將對比 Redis 和 Memcached。我會介紹一些功能上的不同&#xff0c;但主要關注 性能。 首先&#xf…