【C++設計模式】第七篇:橋接模式(Bridge)

注意:復現代碼時,確保 VS2022 使用 C++17/20 標準以支持現代特性。

抽象與實現的解耦之道


1. 模式定義與用途??

核心思想?

  • ?橋接模式:將抽象部分與實現部分分離,使二者可以獨立變化。?
  • 關鍵用途:
    ?1.拆分復雜繼承樹:避免因多維度擴展導致的類爆炸。
    ?2.運行時切換實現:動態組合不同的抽象與實現(如渲染引擎、數據存儲方式)。
  • 經典場景?
    1.圖形庫:形狀(抽象)與渲染API(實現)的組合。
    2.設備控制:遙控器(抽象)與電器設備(實現)的解耦。

2. 模式結構解析

+---------------------+          +---------------------+  
|      Abstraction     |          |   Implementor       |  
+---------------------+          +---------------------+  
| - impl: Implementor |<>------->| + operationImpl()   |  
| + operation(): void |          +---------------------+  
+---------------------+                    ^  ^                                    |  |                              +-----+-------------+  |                              |                   |  
+---------------------+      +-------------------+    +-------------------+  
| RefinedAbstraction  |      | ConcreteImplA     |    | ConcreteImplB     |  
+---------------------+      +-------------------+    +-------------------+  
| + operation()       |      | + operationImpl() |    | + operationImpl() |  
+---------------------+      +-------------------+    +-------------------+  

角色說明?

  1. Abstraction:抽象部分的基類,持有實現部分的引用。
  2. ?RefinedAbstraction:擴展抽象功能的具體類。
  3. Implementor:實現部分的接口。
  4. ConcreteImplementor:實現部分的具體類。

3. 簡單示例:圖形渲染引擎橋接?

?場景:形狀與渲染API解耦

// 實現部分:渲染API接口  
class RenderAPI {  
public:  virtual void renderCircle(float x, float y, float radius) = 0;  virtual ~RenderAPI() = default;  
};  // 抽象部分:形狀基類  
class Shape {  
public:  Shape(RenderAPI& api) : api_(api) {}  virtual void draw() = 0;  
protected:  RenderAPI& api_;  
};  // 客戶端調用  
class Circle : public Shape {  
public:  Circle(RenderAPI& api, float x, float y, float r)  : Shape(api), x_(x), y_(y), radius_(r) {}  void draw() override {  api_.renderCircle(x_, y_, radius_);  }  
private:  float x_, y_, radius_;  
};  

4. 完整代碼:多API與多形狀支持?

步驟1:實現部分(渲染API)

// 實現接口  
class RenderAPI {  
public:  virtual void renderCircle(float x, float y, float radius) = 0;  virtual void renderRect(float x, float y, float w, float h) = 0;  virtual ~RenderAPI() = default;  
};  // OpenGL實現  
class OpenGLAPI : public RenderAPI {  
public:  void renderCircle(float x, float y, float radius) override {  std::cout << "OpenGL渲染圓形:位置(" << x << "," << y << "), 半徑" << radius << "\n";  }  void renderRect(float x, float y, float w, float h) override {  std::cout << "OpenGL渲染矩形:位置(" << x << "," << y << "), 尺寸" << w << "x" << h << "\n";  }  
};  // Vulkan實現  
class VulkanAPI : public RenderAPI {  
public:  void renderCircle(float x, float y, float radius) override {  std::cout << "Vulkan渲染圓形:位置(" << x << "," << y << "), 半徑" << radius << "\n";  }  void renderRect(float x, float y, float w, float h) override {  std::cout << "Vulkan渲染矩形:位置(" << x << "," << y << "), 尺寸" << w << "x" << h << "\n";  }  
};  

步驟2:抽象部分(形狀與擴展)?

// 抽象基類(使用智能指針管理實現)  
class Shape {  
public:  Shape(std::shared_ptr<RenderAPI> api) : api_(api) {}  virtual void draw() = 0;  virtual ~Shape() = default;  
protected:  std::shared_ptr<RenderAPI> api_;  
};  // 具體形狀:圓形  
class Circle : public Shape {  
public:  Circle(std::shared_ptr<RenderAPI> api, float x, float y, float r)  : Shape(api), x_(x), y_(y), radius_(r) {}  void draw() override {  api_->renderCircle(x_, y_, radius_);  }  
private:  float x_, y_, radius_;  
};  // 具體形狀:矩形  
class Rectangle : public Shape {  
public:  Rectangle(std::shared_ptr<RenderAPI> api, float x, float y, float w, float h)  : Shape(api), x_(x), y_(y), width_(w), height_(h) {}  void draw() override {  api_->renderRect(x_, y_, width_, height_);  }  
private:  float x_, y_, width_, height_;  
};  

步驟3:客戶端動態組合

int main() {  // 創建不同渲染API  auto opengl = std::make_shared<OpenGLAPI>();  auto vulkan = std::make_shared<VulkanAPI>();  // 動態組合形狀與API  Circle glCircle(opengl, 10, 10, 5);  Circle vkCircle(vulkan, 20, 20, 8);  Rectangle glRect(opengl, 5, 5, 10, 6);  glCircle.draw();  // 輸出:OpenGL渲染圓形:位置(10,10), 半徑5  vkCircle.draw();  // 輸出:Vulkan渲染圓形:位置(20,20), 半徑8  glRect.draw();  // 輸出:OpenGL渲染矩形:位置(5,5), 尺寸10x6  
}  

5. 優缺點分析

優點??缺點
分離抽象與實現,減少繼承層次增加類的數量
支持運行時動態切換實現需要設計合理的抽象接口
提升跨平臺、跨模塊的擴展性對簡單場景可能過度設計

6. 調試與優化策略?

?

調試技巧(VS2022)??

  1. ?驗證橋接連接
    draw()方法中設置斷點,檢查api_指針是否指向正確的實現對象。
  2. 多態類型識別
    使用typeid(*api_).name()輸出實際類型(需啟用RTTI)。?

性能優化?

  1. ?緩存實現對象
    對頻繁使用的實現(如OpenGLAPI)使用單例或對象池。
  2. 移動語義優化
// 使用移動語義傳遞渲染API所有權  
Shape(std::shared_ptr<RenderAPI>&& api) : api_(std::move(api)) {}  

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

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

相關文章

在 Spring Boot 2.7.x 中引入 Kafka-0.9 的實踐

文章目錄 在 Spring Boot 2.7.x 中引入 Kafka-0.9 的實踐一、下載 Kafka-0.9二、啟動 Zookeeper 和 Kafka三、創建 Spring Boot 項目四、引入 kafka 依賴五、移除 Kafka 自動配置六、編寫 Kafka 生產者6.1 Kafka配置類6.2 生產者監聽類 七、編寫Controller發送Kafka八、驗證消費…

字符串中的數字之和

題目描述 程序要求能夠提取輸入的字符串中的數字&#xff0c;將數字累加&#xff0c;得到數字之和&#xff0c;如輸入的字符串為"abc76wet23er1.",應該提取數字76,23,1,求和后&#xff0c;即76231100。 輸入格式: 輸入一個字符串&#xff0c;字符串長度不超過100.…

77.ObservableCollection使用介紹1 C#例子 WPF例子

可觀察集合ObservableCollection using System; using System.Collections.ObjectModel;class Program {static void Main(){// 創建一個可觀察集合ObservableCollection<string> list new ObservableCollection<string>();// 注冊集合變化事件list.CollectionCh…

ORACLE 執行查詢語句慢(不走對應索引)

1. 索引未被創建或未正確創建 確保為查詢中涉及的列創建了索引。例如&#xff0c;如果你經常需要按column_name列進行查詢&#xff0c;確保已經為該列創建了索引,索引創建語句 CREATE INDEX idx_column_name ON table_name(column_name); 2、索引不可用 原因:索引可能被標記為不…

r1-reasoning-rag:一種新的 RAG 思路

最近發現了一個開源項目&#xff0c;它提供了一種很好的 RAG 思路&#xff0c;它將 DeepSeek-R1 的推理能力結合 Agentic Workflow 應用于 RAG 檢索 項目地址 https://github.com/deansaco/r1-reasoning-rag.git 項目通過結合 DeepSeek-R1、Tavily 和 LangGraph&#xff0c;實現…

服務器硬件配置統計

服務器型號和SN # dmidecode -t system | grep -E "Product Name|Serial Number" | awk -F: {print $2} PowerEdge R7515 4567CPU型號和物理CPU數量 echo "$(lscpu | grep "Model name" | cut -d : -f2 | sed s/^ *//) x $(lscpu | grep "Soc…

Hadoop、Spark、Flink Shuffle對比

一、Hadoop的shuffle 前置知識&#xff1a; Map任務的數量由Hadoop框架自動計算&#xff0c;等于分片數量&#xff0c;等于輸入文件總大小 / 分片大小&#xff0c;分片大小為HDFS默認值128M&#xff0c;可調 Reduce任務數由用戶在作業提交時通過Job.setNumReduceTasks(int)設…

Docker的常用鏡像

Docker的常用鏡像命令主要包括鏡像的查看、搜索、拉取、刪除、構建等操作&#xff0c;以下是綜合多個來源的總結&#xff1a; 一、基礎鏡像操作 查看本地鏡像 docker images? 顯示所有本地鏡像&#xff0c;包含倉庫名&#xff08;REPOSITORY&#xff09;、標簽&#xff08;TAG…

車載以太網測試-3【Wireshark介紹】

1 摘要 Wireshark 是一款開源的網絡協議分析工具&#xff0c;廣泛用于網絡故障排查、協議分析、網絡安全檢測等領域。它能夠捕獲網絡數據包&#xff0c;并以詳細的、可讀的格式顯示這些數據包的內容。廣泛應用于車載網絡測試&#xff0c;是車載網絡測試工程師必須掌握的工具。…

基于跨模態地圖學習的視覺語言導航

前言 本工作開展的背景&#xff1a; 人類和其他物種構建類似地圖的環境表示來完成尋路&#xff1a; &#xff08;1&#xff09;當人類只使用現成的駕駛或步行路徑到達目標時&#xff0c;構建認知地圖和獲取空間知識的能力就會下降&#xff1b; &#xff08;2&#xff09;另…

nodejs關于后端服務開發的探究

前提 在當前的環境中關于web server的主流開發基本上都是java、php之類的&#xff0c;其中java spring系列基本上占了大頭&#xff0c;而python之流也在奮起直追&#xff0c;但別忘了nodejs也是可以做這個服務的&#xff0c;只是位置有點尷尬&#xff0c;現在就來探究下nodejs…

Ubuntu20.04本地配置IsaacGym Preview 4的G1訓練環境(一)

Ubuntu20.04本地配置IsaacGym Preview 4的G1訓練環境 配置conda虛擬環境安裝pytorch、cuda和cudnn安裝IsaacGym Preview 4配置rsl_rl配置unitree_rl_gym配置unitree_sdk2py 寫在前面&#xff0c;要求完成anaconda配置&#xff0c;若沒完成&#xff0c;請參考本人其余博客&#…

RangeError: Maximum call stack size exceeded

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》、《前端求職突破計劃》 &#x1f35a; 藍橋云課簽約作者、…

八卡5090服務器首發亮相!

AI 人工智能領域熱度居高不下。OpenAI 的 GPT - 4 憑強悍語言處理能力&#xff0c;在內容創作、智能客服等領域廣泛應用。清華大學團隊的 DeepSeek 大模型在深度學習訓練優勢突出&#xff0c;正促使各行業應用端算力需求向推理主導轉變&#xff0c;呈爆發式增長 。 隨著 DeepS…

計算機視覺|Swin Transformer:視覺 Transformer 的新方向

一、引言 在計算機視覺領域的發展歷程中&#xff0c;卷積神經網絡&#xff08;CNN&#xff09; 長期占據主導地位。從早期的 LeNet 到后來的 AlexNet、VGGNet、ResNet 等&#xff0c;CNN 在圖像分類、目標檢測、語義分割等任務中取得了顯著成果。然而&#xff0c;CNN 在捕捉全…

【Leetcode 每日一題】2597. 美麗子集的數目

問題背景 給你一個由正整數組成的數組 n u m s nums nums 和一個 正 整數 k k k。 如果 n u m s nums nums 的子集中&#xff0c;任意兩個整數的絕對差均不等于 k k k&#xff0c;則認為該子數組是一個 美麗 子集。 返回數組 n u m s nums nums 中 非空 且 美麗 的子集數…

常見Web應用源碼泄露問題

文章目錄 前言一、常見的源碼泄露漏洞git源碼泄露SVN源碼泄露DS_Store文件泄漏網站備份壓縮文件泄露WEB-INF/web.xml泄露CVS泄露.hg源碼泄露Bazaar/bzr泄露.swp文件泄露 前言 在Web應用方面對于安全來說&#xff0c;可能大家對SQL注入、XSS跨站腳本攻擊、文件上傳等一些漏洞已…

記錄一次wifi版有人物聯串口服務器調試經過

1、首先買了一個華為的wifi路由器&#xff0c;連接上以后&#xff0c;設置好網絡名字和wifi密碼 2、用網線連接串口服務器&#xff0c;通過192.168.1.1登錄&#xff0c;進行配置 找到無線客戶端配置&#xff0c;先在基本配置中打開5G配置&#xff0c;然后再去5.8G配置中設置 …

Android 平臺架構系統啟動流程詳解

目錄 一、平臺架構模塊 1.1 Linux 內核 1.2 硬件抽象層 (HAL) 1.3 Android 運行時 1.4 原生 C/C 庫 1.5 Java API 框架 1.6 系統應用 二、系統啟動流程 2.1 Bootloader階段 2.2 內核啟動 2.3 Init進程&#xff08;PID 1&#xff09; 2.4 Zygote與System Serv…

【Windows下Gitbook快速入門使用】

Windows下Gitbook快速入門使用 1 工具安裝1.1 Node.js下載安裝1.1 環境變量1.2 npm配置1.3 安裝gitbook 2 gitbook使用2.1 gitbook 無法執行2.2 gitbook常用命令 Gitbook是一個軟件&#xff0c;使用Git和Markdown來編排書本&#xff1b; GitBook helps you pushlish beautiful …