C#設計模式學習筆記:(7)橋接模式

来源:https://www.cnblogs.com/atomy/archive/2020/01/19/12209509.html
-Advertisement-
Play Games

本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7699301.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講結構型設計模式的第二個模式--橋接模式,也有叫橋模式的。橋在我們現實生活中經常是連接著A地和B地,再往後來發展,橋引申為一種紐 帶, ...


    本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7699301.html,記錄一下學習過程以備後續查用。

    一、引言

    今天我們要講結構型設計模式的第二個模式--橋接模式,也有叫橋模式的。橋在我們現實生活中經常是連接著A地和B地,再往後來發展,橋引申為一種紐

帶,比如,絲綢之路是連接亞洲和歐洲的橋梁。有了橋,我們出行更方便了,不需要繞路或搭船。針對橋的使用環境來說,橋解決了跨越和銜接的問題。在

設計模式中的橋接模式也有類似的概念,是連接了兩個不同維度的東西,而且這兩個維度又有強烈的變化。

    二、橋接模式介紹

    橋接模式:英文名稱--Bridge Pattern;分類--結構型。

    2.1、動機(Motivate)

    一般游戲場景中,裝備都會有自己固有的邏輯。比如槍支,有型號,同時又支持在不同的介質平臺上使用,這樣就使得游戲的裝備具有了兩個變化的維度。

一個變化的維度為“平臺的變化”,另一個變化的維度為“型號的變化”。如果我們要寫代碼實現這款游戲,難道我們針對每種平臺都實現一套獨立的裝備嗎?復

用在哪裡?如何應對這種“多維度的變化”?如何利用面向對象技術來使得裝備可以輕鬆地沿著“平臺”和“型號”兩個方向變化,而不引入額外的複雜度?

    2.2、意圖(Intent)

    將抽象部分與實現部分分離,使它們都可以獨立地變化。--《設計模式》Gof

    橋接模式不能只是認為是抽象和實現的分離,它其實並不僅限於此。其實兩個都是抽象的部分,更確切的理解,應該是將一個事物中多個維度的變化分離。

    2.3、結構圖(Structure)

    2.4、模式的組成

    橋接模式的結構包括Abstraction、RefinedAbstraction、Implementor、ConcreteImplementorA和ConcreteImplementorB五個部分,其中:

    1)抽象化角色(Abstraction):抽象化給出定義,並保存一個對實現化對象(Implementor)的引用。

    2)修正抽象化角色(Refined Abstraction):擴展抽象化角色,改變和修正父類對抽象化的定義。

    3)實現化角色(Implementor):這個角色給出實現化角色的介面,但不給出具體的實現。必須指出的是,這個介面不一定與抽象化角色的介面定義相同。

實際上,這兩個介面可以非常不一樣。實現化角色應當只給出底層操作,而抽象化角色應當只給出基於底層操作的更高一層的操作。

    4)具體實現化角色(Concrete Implementor):這個角色給出實現化角色介面的具體實現。

    在橋接模式中,兩個類Abstraction和Implementor分別定義了抽象與行為類型的介面,通過調用兩介面的子類實現抽象與行為的動態組合。

    2.5、橋接模式的具體實現

    今天我們就以資料庫為例來寫該模式的實現。每種資料庫都有自己的版本,但是每種資料庫在不同的平臺上實現又是不一樣的。比如,微軟的SqlServer數

據庫有2000、2005、2008、2012、2014、2016、2017版本,後面還會有更新的版本,並且這些版本都是運行在Windows操作系統下的。如果要提供Lunix

操作系統下的SqlServer怎麼辦呢?如果又要提供IOS操作系統下的SqlServer資料庫該怎麼辦呢?這個情況就可以使用橋接模式,也就是Brige模式。

    下麵看看具體的實現:

    class Program
    {
        /// <summary>
        /// 該抽象類就是抽象介面的定義,該類型就相當於是Abstraction類型。
        /// </summary>
        public abstract class Database
        {
            //通過組合方式引用平臺介面,此處就是橋梁,該類型相當於Implementor類型。
            protected PlatformImplementor platformImplementor;

            //通過構造器註入,初始化平臺實現。
            protected Database(PlatformImplementor implementor)
            {
                platformImplementor = implementor;
            }

            //創建資料庫,該操作相當於Abstraction類型的Operation方法。
            public abstract void Create();
        }

        /// <summary>
        /// 該抽象類就是實現介面的定義,該類型就相當於是Implementor類型。
        /// </summary>
        public abstract class PlatformImplementor
        {
            //該方法就相當於Implementor類型的OperationImp方法
            public abstract void Process();
        }

        /// <summary>
        /// SqlServer2000版本的資料庫,相當於RefinedAbstraction類型。
        /// </summary>
        public class SqlServer2000 : Database
        {
            //構造函數初始化
            public SqlServer2000(PlatformImplementor implementor) : base(implementor) { }

            public override void Create()
            {
                platformImplementor.Process();
            }
        }

        /// <summary>
        /// SqlServer2005版本的資料庫,相當於RefinedAbstraction類型。
        /// </summary>
        public class SqlServer2005 : Database
        {
            //構造函數初始化
            public SqlServer2005(PlatformImplementor implementor) : base(implementor) { }

            public override void Create()
            {
                platformImplementor.Process();
            }
        }

        /// <summary>
        /// SqlServer2000版本的資料庫針對Unix操作系統的具體實現,相當於ConcreteImplementorA類型。
        /// </summary>
        public class SqlServer2000UnixImplementor : PlatformImplementor
        {
            public override void Process()
            {
                Console.WriteLine("SqlServer2000針對Unix操作系統的具體實現。");
            }
        }

        /// <summary>
        /// SqlServer2005版本的資料庫針對Unix操作系統的具體實現,相當於ConcreteImplementorB類型。
        /// </summary>
        public sealed class SqlServer2005UnixImplementor : PlatformImplementor
        {
            public override void Process()
            {
                Console.WriteLine("SqlServer2005針對Unix操作系統的具體實現。");
            }
        }

        static void Main(string[] args)
        {
            #region 橋接模式
            //針對不同平臺進行擴展,也就是子類化,這個是獨立變化的。
            PlatformImplementor SqlServer2000UnixImp = new SqlServer2000UnixImplementor();

            //資料庫版本也可以進行擴展和升級,也進行獨立的變化。
            Database SqlServer2000Unix = new SqlServer2000(SqlServer2000UnixImp);

            //以上就是兩個維度的變化。

            //現在就可以針對Unix操作系統進行操作了。
            SqlServer2000Unix.Create();

            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    三、橋接模式的實現要點

    1)Bridge模式使用“對象間的組合關係”解耦了抽象和實現之間固有的綁定關係,使得抽象和實現可以沿著各自的維度來變化。

    2)所謂抽象和實現沿著各自維度的變化,即“子類化”它們,得到各個子類之後,便可以任意組合它們,從而獲得不同平臺上的不同型號。

    3)Bridge模式有時候類似於多繼承方案,但是多繼承方案往往違背了類的單一職責原則(即一個類只有一個變化的原因),復用性比較差。Bridge模式對

比於多繼承方案是更好的解決方法。

    4)Bridge模式的應用一般在“兩個非常強的變化維度”。有時候即使有兩個變化的維度,但是某個方向的變化維度並不劇烈,換言之兩個變化不會導致縱橫

交錯的結果,並不一定要使用Bridge模式。

    3.1、橋接模式的優點

    1)把抽象介面與其實現解耦。

    2)抽象和實現可以獨立擴展,不會影響到對方。

    3)實現細節對客戶透明,對使用隱藏了具體的實現細節。

    3.2、橋接模式的缺點

    1)增加了系統的複雜度

    3.3、橋接模式的使用場景

    1)一個系統需要在構件的抽象化角色和具體化角色之間添加更多的靈活性,避免在兩個層次之間建立靜態的聯繫。

    2)設計要求實現化角色的任何改變不應當影響客戶端,或者實現化角色的改變對客戶端是完全透明的。

    3)需要跨越多個平臺的圖形和視窗系統上。

    4)一個類存在兩個獨立變化的維度,且兩個維度都需要進行擴展。

    四、.NET中橋接模式的實現

    學習中……,如果誰有好的代碼分享,可以貼出來。

    五、總結

    橋接模式是連接客戶端代碼和具體實現代碼的一座橋梁,同時它也隔離了實現代碼的改變對客戶代碼的影響。在意圖中所說的抽象和實現,這兩個部分其

實都是高度抽象的,前面“抽象”是指定義了針對客戶端的介面,客戶端其實使用的是Abstract類型或者是RefinedAbstract類型,這兩個類型只是介面,具體的

實現委托給了Implementor類型了。Abstract類型子類化的擴展也演變成Implementor子類化的變化。依個人理解,Abstract類型和其子類型在客戶端代碼和真

正實現的代碼之間起到了橋梁的作用,隔離了Implementor實現代碼的變化,讓客戶端更穩定,所以意圖才說是講抽象部分和它的實現部分隔離。


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

-Advertisement-
Play Games
更多相關文章
  •   Spark Streaming對實時數據流進行分析處理,源源不斷的從數據源接收數據切割成一個個時間間隔進行處理;    流處理與批處理有明顯區別,批處理中的數據有明顯的邊界、數據規模已知;而流處理數據流並沒有邊界,也未知數據規模;    ...
  • 函數 函數參數 參數及返回值類型 可選參數 預設參數 剩餘參數 箭頭函數 基本示例 for of 迴圈 for 迴圈 forEach 不支持 break for in 會把數組當作對象來遍歷 for of 支持 break 類型推斷(Type Inference) 類型相容性 模塊 概念 模塊通信: ...
  • 解構賦值 數組解構 上面的寫法等價於: 利用解構賦值交換變數: 函數參數解構: 解構剩餘參數: 也可以忽略其它參數: 或者跳過解構: 對象解構 示例一: 就像數組解構,你可以用沒有聲明的賦值: 你可以在對象里使用 語法創建剩餘變數: 屬性解構重命名 你也可以給屬性以不同的名字: 註意,這裡的冒號 不 ...
  • Hello World 新建 並寫入以下內容: 安裝編譯器: 編譯: 修改 文件中的代碼,為 greeter 函數的參數 person 加上類型聲明 : 重新編譯執行。 讓我們繼續修改: 重新編譯,你將看到如下錯誤: 介面(Interface) 類(Class) 變數聲明 作用域 重覆聲明 塊級作用 ...
  • TypeScript 介紹 TypeScript 是什麼 TypeScript 是 JavaScript 的強類型版本。然後在編譯期去掉類型和特有語法,生成純粹的 JavaScript 代碼。由於最終在瀏覽器中運行的仍然是 JavaScript,所以 TypeScript 並不依賴於瀏覽器的支持,也 ...
  • 隨著你的 Python 項目越來越多,你會發現不同的項目會需要 不同的版本的 Python 庫。同一個 Python 庫的不同版本可能不相容。虛擬環境可以為每一個項目安裝獨立的 Python 庫,這樣就可以隔離不同項目之間的 Python 庫,也可以隔離項目與操作系統之間的 Python 庫。 1. ...
  • http請求在我們實際工作中天天見,為了不重覆造輪子,現在分享一下最近的一次封裝整理,供大家參考,交流,學習! ...
  • static void AggregateExceptionsDemo() { var task1 = Task.Factory.StartNew(() => { var child1 = Task.Factory.StartNew(() => { throw new CustomException ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...