深入理解設計模式(20):橋接模式

来源:https://www.cnblogs.com/xuwendong/archive/2019/03/08/10319474.html
-Advertisement-
Play Games

一、什麼是橋接模式 橋接模式(Bridge Pattern):將抽象部分與它的實現部分分離,使它們都可以獨立地變化。它是一種對象結構型模式,又稱為柄體(Handle and Body)模式或介面(Interface)模式。 二、橋接模式的結構 在橋接模式結構圖中包含如下幾個角色: ●Abstract ...


一、什麼是橋接模式

橋接模式(Bridge Pattern):將抽象部分與它的實現部分分離,使它們都可以獨立地變化。它是一種對象結構型模式,又稱為柄體(Handle and Body)模式或介面(Interface)模式。

二、橋接模式的結構

在橋接模式結構圖中包含如下幾個角色:

●Abstraction(抽象類:用於定義抽象類的介面,它一般是抽象類而不是介面,其中定義了一個Implementor(實現類介面)類型的對象並可以維護該對象,它與Implementor之間具有關聯關係,它既可以包含抽象業務方法,也可以包含具體業務方法。

●RefinedAbstraction(擴充抽象類):擴充由Abstraction定義的介面,通常情況下它不再是抽象類而是具體類,它實現了在Abstraction中聲明的抽象業務方法,在RefinedAbstraction中可以調用在Implementor中定義的業務方法。

●Implementor(實現類介面):定義實現類的介面,這個介面不一定要與Abstraction的介面完全一致,事實上這兩個介面可以完全不同,一般而言,Implementor介面僅提供基本操作,而Abstraction定義的介面可能會做更多更複雜的操作。Implementor介面對這些基本操作進行了聲明,而具體實現交給其子類。通過關聯關係,在Abstraction中不僅擁有自己的方法,還可以調用到Implementor中定義的方法,使用關聯關係來替代繼承關係。

●ConcreteImplementor(具體實現類):具體實現Implementor介面,在不同的ConcreteImplementor中提供基本操作的不同實現,在程式運行時,ConcreteImplementor對象將替換其父類對象,提供給抽象類具體的業務操作方法。

三、橋接模式的使用場景

  • 當對象存在多種變化的因素時,考慮對其變化的因素和場景進行抽象,然後進行橋接;如筆擁有不同的功能。

  • 當多個對象存在多種變化的因素時,考慮將這部分變化的部分抽象出來再聚合進來;比如不同品牌的電腦安裝不同的系統、使用不同的軟體等,相當於將第一條進行橫向擴展,增加橋接的數量。

四、橋接模式的優缺點

優點:

  (1)分離抽象介面及其實現部分。橋接模式使用“對象間的關聯關係”解耦了抽象和實現之間固有的綁定關係,使得抽象和實現可以沿著各自的維度來變化。所謂抽象和實現沿著各自維度的變化,也就是說抽象和實現不再在同一個繼承層次結構中,而是“子類化”它們,使它們各自都具有自己的子類,以便任何組合子類,從而獲得多維度組合對象。

        (2)在很多情況下,橋接模式可以取代多層繼承方案,多層繼承方案違背了“單一職責原則”,復用性較差,且類的個數非常多,橋接模式是比多層繼承方案更好的解決方法,它極大減少了子類的個數。

        (3)橋接模式提高了系統的可擴展性,在兩個變化維度中任意擴展一個維度,都不需要修改原有系統,符合“開閉原則”。

缺點:

  (1)橋接模式的使用會增加系統的理解與設計難度,由於關聯關係建立在抽象層,要求開發者一開始就針對抽象層進行設計與編程。

        (2)橋接模式要求正確識別出系統中兩個獨立變化的維度,因此其使用範圍具有一定的局限性,如何正確識別兩個獨立維度也需要一定的經驗積累。

五、裝飾,橋接和適配器模式的異同

三者都是結構型的設計模式,而且都存在依賴抽象的情況

適配器模式:

重點強調的是適配的功能。(適配器依賴抽象)

關鍵點是:

·        主體類和適配器類實現相同的介面A

·        主體類依賴適配器類

·        適配器類依賴抽象介面B

·        被適配的類實現抽象介面B

最終的效果就是,主體類可以使用之前不相關的被適配類中的某些功能。

橋接模式:

重點強調的是多維度的變化。(主體類直接依賴抽象)

關鍵點是:

·        主體類依賴抽象A

·        主體類具有多個不同的實現類

·        抽象A具有多個不同的實現類

最終的效果就是,主體類的實現類和抽象的實現類分別可以在兩個維度上進行各自的變化。如果主體類依賴多個抽象,則維度進行增加,方便擴展。

裝飾器模式:

重點強調的是裝飾功能。(主體類不僅依賴抽象,而且實現該抽象介面)

關鍵點是:

·        抽象A具有多個具體子類

·        裝飾器類依賴抽象A

·        裝飾器類實現抽象A

·        裝飾器類存在不同子類

最終的效果就是,(裝飾器實現類)對(原抽象的子類)進行某些方法的功能加強。

六、橋接模式的實現

首先抽象出電視機,提供遙控器改變的行為方法。

/// <summary>
    /// 電視機,提供抽象方法
    /// </summary>
    public abstract class TV
    {
        public abstract void On();
        public abstract void Off();
        public abstract void tuneChannel();
    }

創建具體的電視機,繼承自抽象電視機類:

/// <summary>
    /// 三星牌電視機,重寫基類的抽象方法
    /// </summary>
    public class Samsung:TV
    {
        public override void On()
        {
            Console.WriteLine("三星牌電視機已經打開了");
        }

        public override void Off()
        {
            Console.WriteLine("三星牌電視機已經關掉了");
        }

        public override void tuneChannel()
        {
            Console.WriteLine("三星牌電視機換頻道");
        }
    }

    /// <summary>
    /// 長虹牌電視機,重寫基類的抽象方法
    /// 提供具體的實現
    /// </summary>
    public class ChangHong : TV
    {
        public override void On()
        {
            Console.WriteLine("長虹牌電視機已經打開了");
        }

        public override void Off()
        {
            Console.WriteLine("長虹牌電視機已經關掉了");
        }

        public override void tuneChannel()
        {
            Console.WriteLine("長虹牌電視機換頻道");
        }
    }

然後抽象出概覽中的遙控器,扮演抽象話的角色

/// <summary>
    ///  抽象概念中的遙控器,扮演抽象化角色
    /// </summary>
    public abstract class RemoteControl
    {
        public TV implementor { get; set; }

        /// <summary>
        /// 開電視機
        /// 這裡抽象類中不再提供實現了,而是調用實現類中的實現
        /// </summary>
        public virtual void On()
        {
            implementor.On();
        }

        /// <summary>
        /// 關電視機
        /// </summary>
        public virtual void Off()
        {
            implementor.Off();
        }

        /// <summary>
        /// 換頻道
        /// </summary>
        public virtual void SetChannel()
        {
            implementor.tuneChannel();
        }
    }

創建具體遙控器類:這裡面,我重寫了更換頻道的方法,其實還可以重寫其他的方法

/// <summary>
    /// 具體遙控器類
    /// </summary>
    public class ConcreteRemote:RemoteControl
    {
        /// <summary>
        /// 重寫更換頻道方法
        /// </summary>
        public override void SetChannel()
        {
            Console.WriteLine("重寫更換頻道方法");
            base.SetChannel();
        }
    }

客戶端代碼:

static void Main(string[] args)
        {
            // 創建一個遙控器
            RemoteControl remoteControl = new ConcreteRemote();
            
            //長虹電視機
            remoteControl.implementor = new ChangHong();
            remoteControl.On();
            remoteControl.SetChannel();
            remoteControl.Off();
            Console.WriteLine();

            // 三星牌電視機
            remoteControl.implementor = new Samsung();
            remoteControl.On();
            remoteControl.SetChannel();
            remoteControl.Off();
            Console.Read();
        }

這樣接實現了橋接模式的設計,遙控器的功能實現方法不是在遙控器中去實現了,而是將實現部分用來另一個電視機類去封裝它,遙控器中只包含電視機類的一個引用,通過橋接模式,我們把抽象化和實現化部分分離開了,這樣可以很好應對這兩方面的變化。

七、總結

橋接模式是一個非常有用的模式,在橋接模式中體現了很多面向對象設計原則的思想,包括“單一職責原則”、“開閉原則”、“合成復用原則”、“里氏代換原則”、“依賴倒轉原則”等。熟悉橋接模式有助於我們深入理解這些設計原則,也有助於我們形成正確的設計思想和培養良好的設計風格。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • export 命令 1、概念 export用於定義要輸出的變數(let、var、const、function、class),定義的變數與值是動態綁定關係。 2、命令格式 1、 export 變數定義 2、 export { 變數名 [ as 另名} ,…} 3、 export default 匿名定 ...
  • 在用到 async 和await 做同步請求的時候 在調用 await 方法 的方法外面 必須加上 async 【就是說 有await 方法前面必須加 async 】 await 等待的方法 可以不是 async 的方法,但是返回的類型必須是 Promise 類型 並且將結果 放在 resolve ...
  • 題目 682. 棒球比賽 你現在是棒球比賽記錄員。給定一個字元串列表,每個字元串可以是以下四種類型之一:1.整數(一輪的得分):直接表示您在本輪中獲得的積分數。2. "+"(一輪的得分):表示本輪獲得的得分是前兩輪有效 回合得分的總和。3. "D"(一輪的得分):表示本輪獲得的得分是前一輪有效 回合 ...
  • Element組件網址: http://element-cn.eleme.io/#/zh-CN/component/message Layer組件網址: https://www.layui.com/doc/modules/upload.html 測試介面: 用Postman或者網址http://lo ...
  • (盜圖鎮樓) 多頁應用 每一次頁面跳轉的時候,後臺伺服器都會返回一個新的html文檔,這種類型的網站就是多頁網站,也叫多頁應用。{頁面跳轉——>返回html} 優點是:首屏時間快,seo效果好;缺點是:頁面切換慢; 為什麼多頁應用的首屏時間快? 首屏時間叫做頁面首個屏幕的內容展現時間,當我們訪問頁面 ...
  • "知乎原鏈" 本文為 "中文代碼示例之5分鐘入門TypeScript" 的 "CTS" 版本. CTS作者是@htwx(github). 它實現了關鍵詞和標準庫的所有命名漢化. 本文並未使用附帶的vscode相關插件(包括CTS語言插件和拼音輸入插件), 與原Typescript教程類似, 只用了命 ...
  • 前段時間做了微信自定義分享的功能,分享出的頁面存在邀請碼在ios手機上複製失敗的問題,然而在PC端和安卓機上是沒有問題的。百度了一下,基本給出的解決方案是:ios不單純支持on,為點擊的元素添加空點擊事件:onclick="",眾說芸芸,但是試了下沒一個有用! 如果你複製的文本內容來自是input的 ...
  • 題目 169. 求眾數 給定一個大小為 n 的數組,找到其中的眾數。眾數是指在數組中出現次數大於 ⌊ n/2 ⌋ 的元素。 你可以假設數組是非空的,並且給定的數組總是存在眾數。 示例 1: 示例 2: 眾數(Mode)是統計學名詞,在統計分佈上具有明顯集中趨勢點的數值,代表數據的一般水平(眾數可以不 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...