設計模式(八)結構型:橋接模式詳解

設計模式(八)結構型:橋接模式詳解

橋接模式(Bridge Pattern)是 GoF 23 種設計模式中的結構型模式之一,其核心價值在于將抽象部分與實現部分分離,使它們可以獨立變化。它通過“組合”而非“繼承”來解耦兩個或多個維度的擴展,解決了傳統繼承體系中類爆炸(Class Explosion)的問題。橋接模式是實現“開閉原則”的典范,廣泛應用于圖形渲染系統、數據庫驅動、跨平臺 UI 框架、消息中間件等需要多維度靈活擴展的復雜系統中。它不僅是設計模式,更是一種高層次的架構解耦思想。

一、橋接模式詳細介紹

橋接模式解決的是“多維度變化導致類數量指數級增長”的問題。在傳統面向對象設計中,若一個系統有兩個獨立變化的維度(如“形狀”和“顏色”),通常會通過繼承創建組合類(如 RedCircleBlueCircleRedSquareBlueSquare)。當維度增加時,子類數量呈乘積增長,導致類膨脹、維護困難、擴展性差。

橋接模式通過引入“抽象-實現”分離的雙層結構,將一個類的多個變化維度拆分為獨立的繼承層次,并通過對象組合將它們連接起來。其核心思想是:優先使用對象組合,而不是類繼承

該模式涉及以下核心角色:

  • Abstraction(抽象類):定義高層控制邏輯的接口,包含一個對 Implementor 的引用。它不直接實現功能,而是將具體操作委派給 Implementor
  • RefinedAbstraction(精化抽象類):擴展 Abstraction,提供更具體的抽象行為。可以有多個層次。
  • Implementor(實現接口):定義實現層的接口,通常與平臺、設備、服務等底層細節相關。它獨立于 Abstraction 層演化。
  • ConcreteImplementor(具體實現類):實現 Implementor 接口,提供具體的實現細節。可以有多個,代表不同平臺或策略。

橋接模式的關鍵在于“橋”的建立——Abstraction 持有一個 Implementor 接口的引用,運行時可以動態綁定不同的實現。這使得抽象和實現可以獨立擴展:

  • 新增一種抽象(如新圖形類型)只需擴展 Abstraction 層,無需修改實現。
  • 新增一種實現(如新渲染引擎)只需擴展 Implementor 層,無需修改抽象。

與“策略模式”相比,橋接模式更強調結構分離,通常用于構建穩定的框架;策略模式更強調算法替換,用于運行時動態切換行為。橋接模式的“實現”部分往往代表系統底層或外部依賴,而“抽象”部分代表業務邏輯。

二、橋接模式的UML表示

以下是橋接模式的標準 UML 類圖:

extends
extends
has a
implements
implements
Abstraction
-implementor: Implementor
+Abstraction(Implementor implementor)
+operation()
RefinedAbstractionA
+operation()
RefinedAbstractionB
+operation()
?interface?
Implementor
+implementation()
ConcreteImplementorX
+implementation()
ConcreteImplementorY
+implementation()

圖解說明

  • Abstraction 是抽象層的基類,持有一個 Implementor 接口的引用。
  • RefinedAbstractionARefinedAbstractionB 是具體的抽象類,重寫 operation() 方法,內部調用 implementor.implementation()
  • Implementor 是實現層接口,定義底層操作。
  • ConcreteImplementorXConcreteImplementorY 是具體實現,如不同平臺的渲染引擎。
  • 客戶端通過組合 RefinedAbstractionConcreteImplementor,實現任意搭配,避免了類爆炸。

三、一個簡單的Java程序實例

以下是一個圖形渲染系統的示例,展示如何使用橋接模式分離“圖形類型”和“渲染引擎”兩個維度。

// 實現接口:渲染引擎
interface Renderer {void renderCircle(double radius);void renderRectangle(double width, double height);
}// 具體實現:OpenGL 渲染引擎
class OpenGLRenderer implements Renderer {@Overridepublic void renderCircle(double radius) {System.out.println("OpenGL: Drawing circle with radius " + radius);}@Overridepublic void renderRectangle(double width, double height) {System.out.println("OpenGL: Drawing rectangle " + width + "x" + height);}
}// 具體實現:SVG 渲染引擎
class SVGRenderer implements Renderer {@Overridepublic void renderCircle(double radius) {System.out.println("SVG: Generating circle element with r=" + radius);}@Overridepublic void renderRectangle(double width, double height) {System.out.println("SVG: Generating rectangle element " + width + "x" + height);}
}// 抽象類:圖形
abstract class Shape {protected Renderer renderer;public Shape(Renderer renderer) {this.renderer = renderer;}public abstract void draw();
}// 精化抽象:圓形
class Circle extends Shape {private double radius;public Circle(Renderer renderer, double radius) {super(renderer);this.radius = radius;}@Overridepublic void draw() {renderer.renderCircle(radius);}
}// 精化抽象:矩形
class Rectangle extends Shape {private double width;private double height;public Rectangle(Renderer renderer, double width, double height) {super(renderer);this.width = width;this.height = height;}@Overridepublic void draw() {renderer.renderRectangle(width, height);}
}// 客戶端使用示例
public class BridgePatternDemo {public static void main(String[] args) {// 創建兩種渲染引擎Renderer opengl = new OpenGLRenderer();Renderer svg = new SVGRenderer();// 創建不同圖形,并綁定不同渲染引擎Shape circle1 = new Circle(opengl, 5.0);Shape circle2 = new Circle(svg, 3.0);Shape rect1 = new Rectangle(opengl, 10.0, 4.0);Shape rect2 = new Rectangle(svg, 8.0, 6.0);// 調用 draw,實際執行由具體引擎決定System.out.println("=== Rendering Shapes ===");circle1.draw(); // OpenGL 渲染圓形circle2.draw(); // SVG 渲染圓形rect1.draw();   // OpenGL 渲染矩形rect2.draw();   // SVG 渲染矩形// 動態切換渲染引擎(運行時組合)System.out.println("\n=== Dynamic Engine Switching ===");Circle dynamicCircle = new Circle(opengl, 7.0);dynamicCircle.draw();// 模擬運行時切換為 SVGdynamicCircle.renderer = svg;dynamicCircle.draw();}
}

運行說明

  • Shape 是抽象層,CircleRectangle 是具體圖形。
  • Renderer 是實現層,OpenGLRendererSVGRenderer 是具體渲染引擎。
  • 通過構造函數注入 Renderer,實現“抽象”與“實現”的解耦。
  • 客戶端可以自由組合任意圖形與任意引擎,新增圖形或引擎無需修改對方代碼。

四、總結

特性說明
核心目的分離多維度變化,避免類爆炸
實現機制抽象與實現分離,通過組合連接
關鍵優勢支持獨立擴展、符合開閉原則、提高系統靈活性
主要缺點增加系統復雜性,需謹慎設計接口
適用場景多平臺支持、多數據庫驅動、UI 框架、跨服務適配
不適用場景變化維度少、實現穩定、性能敏感(避免間接調用)

橋接模式與其它模式對比:

  • vs 繼承:繼承是“緊耦合”的垂直擴展,橋接是“松耦合”的水平分離。
  • vs 適配器:適配器解決接口不兼容,橋接解決結構耦合。
  • vs 策略:策略關注算法替換,橋接關注架構分層。

架構師洞見:
橋接模式是“高內聚、低耦合”架構思想的極致體現。在現代系統中,其思想已深入到微服務分層架構插件化系統多租戶平臺的設計中。例如,在云原生應用中,業務邏輯(抽象)與基礎設施(實現)通過橋接模式分離,使同一業務可部署在 AWS、Azure 或私有云上;在數據平臺中,查詢引擎(抽象)與存儲系統(實現)解耦,支持對接 HDFS、S3、數據庫等多種數據源。

未來趨勢是:橋接模式將與領域驅動設計(DDD) 結合,在“防腐層(Anti-Corruption Layer)”中用于隔離核心域與外部系統;在Serverless 架構中,函數邏輯(抽象)與運行時環境(實現)通過橋接解耦,實現跨平臺部署。

掌握橋接模式,有助于設計出可演化、可擴展、可維護的復雜系統。作為架構師,應識別系統中“正交變化維度”,在設計初期就引入橋接結構,避免后期重構成本。橋接不僅是模式,更是架構的分層智慧——它教會我們:真正的靈活性,來自于對變化的預見與分離。

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

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

相關文章

【邊緣填充】——圖像預處理(OpenCV)

目錄 1 邊界復制(BORDER_REPLICATE) 2 邊界反射(BOEDER_REFLECT) 3 邊界反射101(BORDER_REFLECT101) 4 邊界常數(BORDER_CONSTANT) 5 邊界包裹(BORDER_WRAP&#xf…

git同步到github出錯-幾個問題-一天晚上(2025.7.29)

訪問不了github 代理和加速器都正常,但是就是訪問不了這個網站嘗試過幾種方法都不行,后面突然可以了。 之后發現一種情況會不行:同時開啟 同步不了 http連接 https://blog.csdn.net/m0_73972962/article/details/146198392 一堆問題 ssh連接才…

Redis未授權訪問的利用的幾種方法原理以及條件

一、redis通過定時任務反彈shell1.利用條件:需要能夠登錄redis數據庫,并且redis以root用戶運行。同時/var/spool/cron目錄要具有寫和執行權限。二、Redis主從getshell1.原理:在Redis 4.x之后,Redis新增了模塊功能,通過…

DNF 與 YUM 的區別詳解:從 CentOS 7 到 CentOS 9 的演進

🍥 DNF 與 YUM 的區別詳解:從 CentOS 7 到 CentOS 9 的演進標簽:CentOS、YUM、DNF、Linux 包管理、系統升級、兼容性 適用版本:CentOS 7、CentOS 8、CentOS 9🧩 一、背景介紹 CentOS 中使用的包管理工具是 RedHat 系列…

mp核心功能

條件構造器mybatisPlus支持各種復雜的where條件, 滿足日常的開發wrapper類就是條件構造器提供了很多子類條件構造器的用法:QueryWrapper和LambdaQueryWrapper通常用來構建select、delete、update的where條件部分UpdateWrapper和LambdaUpdateWrapper通常只有在set語句…

pcm,msd調制解調仿真

PCM(脈沖編碼調制)和MSD(多符號差分)調制解調系統的MATLAB仿真代碼。 PCM (脈沖編碼調制) 仿真 %% PCM調制解調仿真 clear; clc; close all;% 參數設置 Fs 8000; % 采樣頻率 (Hz) t_duration 0.02; % 信號持續時間 (秒…

【網絡安全】信息網絡安全建設方案(WORD)

1.1 安全整體架構 1.2 安全建設拓撲 1.3 安全建設內容與目標 2.1 用戶側安全建設思路 2.2 用戶側安全建設拓撲 2.3 用戶側安全建設內容 2.3.1 PKI 升級改造 2.3.2 安全防護 2.3.3 安全檢測 2.3.4 安全管理 3.1 跨網安全訪問與交換平臺安全建設思…

微服務 01

微服務是一種軟件架構風格,它是以專注于單一職責的很多小型項目為基礎,組合出復雜的大型應用。 (對應的是單體架構風格) 一、認識微服務 1、單體架構 單體架構:將業務的所有功能集中在一個項目中開發,打…

20250726讓榮品的PRO-RK3566開發板使用TF卡啟動

20250726讓榮品的PRO-RK3566開發板使用TF卡啟動 2025/7/26 8:58緣起:需要升級 榮品的PRO-RK3566核心板的 底板上的FPGA程序。 由于沒有使用RK809的電量計功能,板子一上電就會被關機!^_于是給生產線制作了一張TF卡/啟動卡,插到底板…

Selenium使用指南

🍅 點擊文末小卡片,免費獲取軟件測試全套資料,資料在手,漲薪更快 概述selenium是網頁應用中最流行的自動化測試工具,可以用來做自動化測試或者瀏覽器爬蟲等。官網地址為:相對于另外一款web自動化測試工具QT…

[機緣參悟-235]:通過AI人工升級網絡的工作方式和特征理解人的思維方式

AI人工神經網絡通過模擬生物神經元連接機制、構建層級化特征提取結構,并結合數據驅動的學習方式,為理解人類思維方式提供了技術參照框架,但其本質仍是基于統計的模式匹配,與人類意識層面的思維存在根本差異。以下從其工作方式、基…

【C#補全計劃:類和對象(七)—— 重寫虛方法】

一、virtual和override1. 問題引入:使用里氏替換原則時,使用父類容器裝載子類對象,若不使用virtual和override而是使用new,當子類調用兩個類共有的方法時,調用的是父類的方法而不是子類的方法:using System…

TCPIP之常用協議

一、TCPIP之網絡支撐協議 1.ARP ARP是網絡層協議,在同一廣播域內,將IP地址解析成MAC地址. 1.1 無故ARP 請求型無故ARP 設備在網絡中不管是自動獲取ip地址還是手動配置ip地址,設備都會發送請求型無故ARP檢查這個ip地址是否有重復的。 應…

網絡之路24:VLAN基礎實驗

正文共:2345 字 18 圖,預估閱讀時間:3 分鐘目錄網絡之路第一章:Windows系統中的網絡0、序言1、Windows系統中的網絡 1.1、桌面中的網卡 1.2、命令行中的網卡 1.3、路由表 1.4、家用路由器網絡之路第二章:認識企業設備2…

基于Verilog的神經網絡加速器設計

本設計實現了一個高效的神經網絡加速器,專注于卷積神經網絡(CNN)的核心計算功能。該設計具有以下創新點: 并行處理架構:同時處理多個卷積窗口,提高計算吞吐量 動態權重加載:支持運行時更新卷積核權重 流水線優化:卷積、激活、池化三級流水線設計 可配置參數:支持不同尺寸…

基于springboot的零食商城的設計與實現/零食銷售系統的設計與實現

用戶:注冊,登錄,商品信息,團購商品,公告資訊,后臺管理,在線客服,購物車,個人中心管理員:登錄,個人中心,用戶管理,商品類型…

《劍指offer》-算法篇-位運算

題目二進制中“1”的個數代碼實現二進制中“1”的個數題目描述:輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼表示。思路:求“1”的個數等價于求n-1與n進行“與”運算后不等于0所需要的運算次數。注意:這里的整數可能…

項目上線中的跨域問題

本文將深入解析跨域問題的本質,并提供實用的解決方案。引言 跨域問題可以說是前端開發者的"老朋友"了,特別是在項目從開發環境遷移到生產環境時,這個問題更是頻繁出現。許多開發者對跨域的理解停留在表面,導致在項目上線…

dubbo應用之3.0新特性(響應式編程)(2)

一、介紹 Dubbo 3.0 的響應式編程基于 Triple 協議和 Reactor/RxJava 實現,支持全鏈路異步非阻塞通信。它通過引入 Mono、Flux 等響應式類型,打通跨進程的數據流式傳輸,天然支持反壓、限流等控制能力。相比傳統基于 CompletableFuture 的異步方式,響應式編程更適用于高并發…

力扣-22.括號生成

題目鏈接 22.括號生成 class Solution {List<String> res new ArrayList<>();StringBuilder path new StringBuilder();void backtracking(int n, int left, int right) {if (left right 2 * n) {res.add(path.toString());return;}if (left < n) {path.a…