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

C# 設計模式精講:適配器模式 - 類適配器與物件適配器的雙重實現

     編輯:關於C語言

前言:不兼容介面的「轉接頭」

現實中,手機充電器將 220V 市電轉為 5V 直流電,讓手機能安全充電。軟體開發中,當第三方庫介面與既有系統介面不匹配時,適配器模式扮演同樣角色:將一個類的介面轉換成客戶端期望的另一個介面,使原本無法協作的類能夠共同工作。

一、 模式結構與兩種變體

適配器模式 UML 結構圖

類型核心機制C# 實現關鍵優缺點
類適配器 多重繼承 (繼承 Adaptee + 實作 Target) C# 不支援多重繼承類別,故 Target 必須是介面,Adaptee 可以是類別 可覆寫 Adaptee 行為;但受限於單繼承
物件適配器 組合/委派 (持有 Adaptee 參考 + 實作 Target) Target 可為介面或抽象類別;Adaptee 為成員欄位 靈活適用於 Adaptee 所有子類;無法輕易覆寫 Adaptee 行為

二、 實戰範例:二孔插頭轉三孔插座

客戶端 (電器) 擁有二孔插頭 (`TwoHole`),牆上插座為三孔介面 (`IThreeHole`)。適配器 (`PowerAdapter`) 橋接兩者。

1. 類適配器實作 (繼承 + 實作介面)

// 目標介面:客戶端期望的三孔插座
public interface IThreeHole
{
    void Request(); // 三孔標準方法
}

// 被適配者:現有的二孔插頭
public abstract class TwoHole
{
    public void SpecificRequest()
    {
        Console.WriteLine("我是兩個孔的插頭,提供基本供電。");
    }
}

// 類適配器:繼承 TwoHole,實作 IThreeHole
public class ClassPowerAdapter : TwoHole, IThreeHole
{
    public void Request()
    {
        // 內部委派給被適配者的具體方法
        this.SpecificRequest();
        Console.WriteLine("【類適配器】轉接完成,現在提供三孔介面。");
    }
}

// 客戶端測試
public static void TestClassAdapter()
{
    IThreeHole adapter = new ClassPowerAdapter();
    adapter.Request(); // 輸出兩行訊息
}

2. 物件適配器實作 (組合 + 繼承/實作)

// 目標角色:這裡改為抽象類別,展示靈活性
public abstract class ThreeHoleBase
{
    public virtual void Request() { /* 預設實作或為空 */ }
}

// 被適配者:普通類別 (不再是 abstract)
public class TwoHolePlug
{
    public void SpecificRequest()
    {
        Console.WriteLine("我是兩個孔的插頭 (物件適配器版)。");
    }
}

// 物件適配器:繼承目標,持有被適配者實例
public class ObjectPowerAdapter : ThreeHoleBase
{
    private readonly TwoHolePlug _adaptee = new TwoHolePlug(); // 組合

    public override void Request()
    {
        _adaptee.SpecificRequest(); // 委派
        Console.WriteLine("【物件適配器】轉接完成,現在提供三孔介面。");
    }
}

// 客戶端測試
public static void TestObjectAdapter()
{
    ThreeHoleBase adapter = new ObjectPowerAdapter();
    adapter.Request();
}

三、 核心差異深度解析

  1. 耦合度:類適配器與 Adaptee 是「是一種」關係 (繼承),耦合緊密;物件適配器是「有一個」關係 (組合),耦合鬆散。
  2. 擴展性:物件適配器可適配 Adaptee 及其所有子類;類適配器綁定具體 Adaptee 類別。
  3. 行為覆寫:類適配器可輕易 Override Adaptee 的虛擬方法;物件適配器需建立 Adaptee 子類再組合,較繁瑣。
  4. C# 語言限制:因單繼承,類適配器強制 Target 為介面;物件適配器無此限制。

四、 實際開發中的決策指南

  • **優先選擇物件適配器**:符合「組合優於繼承」原則,靈活度高,符合現代設計習慣。
  • **使用類適配器的場景**:需覆寫 Adaptee 部分行為、Adaptee 為 sealed 無法繼承時 (但類適配器也繼承不了 sealed 類),或極簡單場景下減少一個物件建立開銷。
  • **雙向適配器**:若需在雙向系統中使用 (既作 Target 又作 Adaptee),類適配器因多重繼承天然適合,物件適配器需同時持有兩個介面參考。

五、 .NET 框架應用場景

  • 資料提供者:`DbDataAdapter` 適配不同資料庫命令介面。
  • 集合包裝:`List` 實作 `IList`、`ICollection`、`IEnumerable` 等多介面,本質是適配不同消費者期望。
  • 舊系統整合:將 Legacy COM 元件透過 RCW (Runtime Callable Wrapper) 適配為 .NET 介面。

六、 總結

適配器模式是系統整合、遷移、第三方庫引入時的「萬能轉接頭」。掌握類適配器 (繼承)與物件適配器 (組合)的差異,並在 C# 單繼承語境下做正確選擇,是架構師處理介面不兼容問題的基本功。記住:**預設選組合,特殊才繼承。**

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