Bridge 橋接模式簡介與 C# 範例【結構型2】【設計模式來了_7】

2023-10-09 21:01:28

〇、簡介

1、什麼是橋接模式?

一句話解釋:

  通過一個類的抽象,與另一個類的抽象關聯起來,當做橋。此後不管兩個抽象類的實現有多少種,均可以通過這個橋來將兩個物件聯絡起來。

橋接,顧名思義就是用橋來連線河兩岸,將原本不關聯的兩部分聯絡起來,且不影響兩岸的各自演化,演化出來的不同物件仍可以通過這個橋連線。

橋接設計模式是一種結構型設計模式,它通過將抽象與其實現分離來實現鬆耦合。這種模式可以使得抽象和實現可以獨立地進行擴充套件,而不會相互影響。

官方意圖描述:將抽象部分與它的實現部分分離,使它們可以獨立地變化。

一個比喻:(班主任為學生訂餐)

  學生和餐品相當於兩個變化的類,均可以增加或減少,老師就相當於橋接模式中的橋。學生想吃什麼套餐,可以通過老師來對應到具體的套餐類別。

2、優缺點和適用場景

  • 分離抽象介面及其實現部分。橋接模式使用「物件間的關聯關係」解耦了抽象和實現之間固有的繫結關係,使得抽象和實現可以沿著各自的維度來變化。
  • 在很多情況下,橋接模式可以取代多層繼承方案,多層繼承方案違背了「單一職責原則」,複用性較差,且類的個數非常多,橋接模式是比多層繼承方案更好的解決方法,它極大減少了子類的個數。
  • 橋接模式提高了系統的可延伸性,在兩個變化維度中任意擴充套件一個維度,都不需要修改原有系統,符合「開閉原則」。
  • 橋接模式的使用會增加系統的理解與設計難度,由於關聯關係建立在抽象層,要求開發者一開始就針對抽象層進行設計與程式設計。
  • 橋接模式要求正確識別出系統中兩個獨立變化的維度,因此其使用範圍具有一定的侷限性,如何正確識別兩個獨立維度也需要一定的經驗積累。

適用場景:

  • 「抽象部分」和「實現部分」可以以繼承的方式獨立擴充套件而互不影響,在程式執行時可以動態將一個抽象化子類的物件和一個實現化子類的物件進行組合,即系統需要對抽象化角色和實現化角色進行動態耦合。
  • 一個類存在兩個(或多個)獨立變化的維度,且這兩個(或多個)維度都需要獨立進行擴充套件
  • 不希望使用繼承或因為多層繼承導致系統類的個數急劇增加的系統。

實際適用場景:

  • 遊戲開發:在遊戲開發中,可以使用橋接模式將遊戲引擎和場景分離開來,使得使用者可以在不同的場景之間進行切換,而不需要修改遊戲引擎的程式碼。
  • 網路程式設計:在網路程式設計中,可以使用橋接模式將協定和實現分離開來,使得使用者可以在不同的協定之間進行切換,而不需要修改實現的程式碼。
  • 圖形介面開發:在圖形介面開發中,可以使用橋接模式將控制元件的樣式和佈局分離開來,使得使用者可以在不同的樣式和佈局之間進行切換,而不需要修改程式碼。

參考:https://zhuanlan.zhihu.com/p/58903776

一、程式碼範例

首先一起看下不使用橋接模式的範例

假設我們正在開發一個圖形繪製應用程式,需要支援不同型別的圖形(例如圓形、正方形)以及不同型別的繪製方式(例如紅色、藍色)。在不使用橋接設計模式的情況下,我們可能會建立以下類層次結構:

// 圖形基礎類別
abstract class Shape
{
    public abstract void Draw();
}
// 圓形
class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a circle");
    }
}
// 正方形
class Square : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a square");
    }
}
// 紅色繪製器
class RedColor : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing in red color");
    }
}
// 藍色繪製器
class BlueColor : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing in blue color");
    }
}

在上述程式碼中,我們有一個基礎類別 Shape 和兩個派生類 Circle 和 Square,分別表示圓形和正方形。另外,我們還有兩個派生類 RedColor 和 BlueColor,分別表示紅色和藍色的繪製器。這種實現方式存在一個問題:當我們需要繪製不同顏色的圖形時,必須在每個具體圖形類中新增相應顏色的繪製方法。這導致了類層次結構的爆炸增長,使得程式碼難以維護和擴充套件。

使用橋接設計模式,我們可以將圖形和顏色的實現分離開來。如下範例程式碼,我們定義一個新的抽象類 Color,表示顏色的實現,在 Shape 類中,將顏色的實現作為一個成員變數,並在 Draw 方法中呼叫顏色的 ApplyColor 方法:

class Program
{
    static void Main(string[] args) // 測試一下
    {
        Color red = new Red();
        Color blue = new Blue();
        Shape redCircle = new Circle(red); // 通過將不同的顏色範例傳遞給圖形類別建構函式來繪製不同顏色的圖形
        Shape blueSquare = new Square(blue);
        redCircle.Draw();
        blueSquare.Draw();

        Console.ReadLine();
    }
}
// 顏色基礎類別
abstract class Color
{
    public abstract void ApplyColor();
}
class Red : Color // 紅色
{
    public override void ApplyColor()
    {
        Console.WriteLine("Applying red color");
    }
}
class Blue : Color // 藍色
{
    public override void ApplyColor()
    {
        Console.WriteLine("Applying blue color");
    }
}

// 修改後的圖形基礎類別
abstract class Shape // (目標介面,定義了使用者端期望的操作:Draw)
{
    protected Color color; // 將顏色的實現作為一個成員變數
    public Shape(Color color)
    {
        this.color = color;
    }
    public abstract void Draw();
}
class Circle : Shape // 圓形
{
    public Circle(Color color) : base(color) // (被適配者 Color 的參照)
    { }
    public override void Draw()
    {
        Console.Write("Drawing a circle. ");
        color.ApplyColor(); // 在 Draw 方法中呼叫顏色的 ApplyColor 方法
    }
}
class Square : Shape // 正方形
{
    public Square(Color color) : base(color)
    { }
    public override void Draw()
    {
        Console.Write("Drawing a square. ");
        color.ApplyColor(); // 在 Draw 方法中呼叫顏色的 ApplyColor 方法
    }
}

通過使用橋接設計模式,我們成功地將圖形和顏色的實現解耦,使得它們可以獨立地進行擴充套件。

如果後續需求增加,需要加一個顏色黃色,然後圖形加一個橢圓,此時就可以分別再實現兩個抽象類(Color、Shape)即可。

二、橋接模式的結構

Abstraction:定義抽象類的介面,維護一個指向 Implementor 型別物件的指標。

Implementor:定義實現類的介面,該介面不一定要與 Abstraction 的介面完全一致,事實上這兩個介面可以完全不同。一般來講,Implementor 介面僅提供進本操作,而 Abstraction 則定義了基於這些基本操作的較高層次的操作。

ConcreteInplementor:實現 Implementor 介面並定義它的具體實現。

三、相關模式

AbstractFactory 模式可以用來建立和設定一個特定的 Bridge 模式。

Adapter 模式用來幫助無關的類協同工作,它通常在系統設計完成後才會被使用。然而,Bridge 模式則是在系統開始時就被使用,它使得抽象介面和實現部分可以獨立進行改變。