首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

深入解析 C# 設計模式:橋接模式

     編輯:關於C#

一、橋接模式的核心意圖

橋接模式是結構型設計模式中極具價值且相對複雜的一員。它的核心在於「將抽象化與實現化解耦,使二者可獨立變化」。掌握此模式有助於深入理解面向對象設計原則,特別是開閉原則(OCP)與組合/聚合復用原則(CARP),進而養成良好的設計風格。

雖然《Java 與模式》一書認為橋接模式使用頻率不高,但我更贊同《Design Patterns Explained》作者 Alan Shalloway 與 James R. Trott 的觀點:橋接模式蘊含了許多設計模式的關鍵思想,比其他模式更實用、更複雜。

二、關鍵概念解析

抽象化

指存在於多個實體中的共同概念聯繫。作為一個過程,即忽略部分資訊,將不同實體視為同一實體處理。

實現化

抽象化所給出的具體實現。

脫耦

將兩實體間的強關聯(繼承關係)轉為弱關聯(組合/聚合關係),使抽象化與實現化可相對獨立演化。

三、橋接模式結構與角色

橋接模式結構圖

系統包含兩個平行的等級結構:

  • 抽象化等級結構:由抽象化角色與修正抽象化角色組成。
  • 實現化等級結構:由實現化角色與具體實現化角色組成。

四大核心角色:

  1. 抽象化角色:定義抽象介面,持有實現化對象引用。
  2. 修正抽象化角色:擴展抽象化角色,修正父類定義。
  3. 實現化角色:提供底層操作介面,不涉及具體實現;其介面可與抽象化角色完全不同。
  4. 具體實現化角色:實現實現化角色介面的具體邏輯。

四、結構型示例代碼

// Bridge pattern -- Structural example
using System;

// 抽象化
class Abstraction {
    protected Implementor implementor;
    public Implementor Implementor { set { implementor = value; } }
    virtual public void Operation() { implementor.Operation(); }
}

// 實現化介面
abstract class Implementor {
    abstract public void Operation();
}

// 修正抽象化
class RefinedAbstraction : Abstraction {
    override public void Operation() { implementor.Operation(); }
}

// 具體實現化 A
class ConcreteImplementorA : Implementor {
    override public void Operation() { Console.WriteLine("ConcreteImplementorA Operation"); }
}

// 具體實現化 B
class ConcreteImplementorB : Implementor {
    override public void Operation() { Console.WriteLine("ConcreteImplementorB Operation"); }
}

// 客戶端測試
public class Client {
    public static void Main(string[] args) {
        Abstraction abstraction = new RefinedAbstraction();
        abstraction.Implementor = new ConcreteImplementorA();
        abstraction.Operation();
        abstraction.Implementor = new ConcreteImplementorB();
        abstraction.Operation();
    }
}

五、經典案例:調制解調器問題

《敏捷軟件開發》中的 Modem 案例生動詮釋了橋接模式的威力。早期系統中,Modem 介面派生出 HayesModem、USRoboticsModem 等,符合 OCP/LSP/DIP。後因專用調制解調器(無需撥號)出現,若讓 DedicatedModem 繼承 Modem 並將 dial/hangup 實現為空,會導致後續擴展(如國際長撥號碼長度變更)波及無關的 DedUser 代碼,產生有害依賴。

繼承導致的依賴混亂

使用橋接模式,將「連接策略」與「硬體實現」分離為兩個獨立等級結構,透過組合關係橋接:

橋接模式解決方案

此結構雖較複雜,但完全隔離了變化維度:新增硬體只需擴展實現化層次,新增連接策略只需擴展抽象化層次,互不干擾,且不影響現有客戶端代碼。

六、實戰應用:業務對象與數據對象解耦

// Bridge pattern -- Real World example
using System;
using System.Collections;

// 抽象化:業務對象
class BusinessObject {
    private DataObject dataObject;
    protected string group;
    public BusinessObject(string group) { this.group = group; }
    public DataObject DataObject { set { dataObject = value; } get { return dataObject; } }
    virtual public void Next() { dataObject.NextRecord(); }
    virtual public void Prior() { dataObject.PriorRecord(); }
    virtual public void New(string name) { dataObject.NewRecord(name); }
    virtual public void Delete(string name) { dataObject.DeleteRecord(name); }
    virtual public void Show() { dataObject.ShowRecord(); }
    virtual public void ShowAll() {
        Console.WriteLine("Customer Group: {0}", group);
        dataObject.ShowAllRecords();
    }
}

// 修正抽象化:客戶業務對象
class CustomersBusinessObject : BusinessObject {
    public CustomersBusinessObject(string group) : base(group) {}
    override public void ShowAll() {
        Console.WriteLine(); Console.WriteLine("------------------------");
        base.ShowAll();
        Console.WriteLine("------------------------");
    }
}

// 實現化:數據對象介面
abstract class DataObject {
    abstract public void NextRecord();
    abstract public void PriorRecord();
    abstract public void NewRecord(string name);
    abstract public void DeleteRecord(string name);
    abstract public void ShowRecord();
    abstract public void ShowAllRecords();
}

// 具體實現化:客戶數據對象
class CustomersDataObject : DataObject {
    private ArrayList customers = new ArrayList();
    private int current = 0;
    public CustomersDataObject() {
        customers.Add("Jim Jones"); customers.Add("Samual Jackson");
        customers.Add("Allen Good"); customers.Add("Ann Stills");
        customers.Add("Lisa Giolani");
    }
    public override void NextRecord() { if (current <= customers.Count - 1) current++; }
    public override void PriorRecord() { if (current > 0) current--; }
    public override void NewRecord(string name) { customers.Add(name); }
    public override void DeleteRecord(string name) { customers.Remove(name); }
    public override void ShowRecord() { Console.WriteLine(customers[current]); }
    public override void ShowAllRecords() {
        foreach (string name in customers) Console.WriteLine(" " + name);
    }
}

// 客戶端測試
public class BusinessApp {
    public static void Main(string[] args) {
        CustomersBusinessObject customers = new CustomersBusinessObject("Chicago");
        customers.DataObject = new CustomersDataObject();
        customers.Show(); customers.Next(); customers.Show();
        customers.Next(); customers.Show();
        customers.New("Henry Velasquez"); customers.ShowAll();
    }
}

七、適用場景總結

  • 需在抽象化與實現化間增加靈活性,避免靜態綁定。
  • 實現化變更不應影響客戶端,需對客戶端透明。
  • 系統存在多個抽象化與實現化角色,需動態耦合。
  • 雖可用繼承,但因兩者需獨立變化,故需獨立管理。

橋接模式體現了「面向介面編程」與「組合優於繼承」的精髓,是應對多維度變化的利器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved