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

C# 設計模式精講:適配器模式雙重實現(類適配器 vs 物件適配器)

     編輯:關於C語言

前言

適配器模式是結構型模式中的經典,解決「介面不相容」問題:將一個類的介面轉換為客戶端期望的另一個介面,使原本無法協作的類能夠合作。本文以 C# 為載體,完整展示類適配器(繼承)與物件適配器(組合/委派)兩種形式的代碼實現、結構差異、優劣勢對比、適用場景,並延伸討論 C# 介面與類的多重實現機制對模式的影響。

模式角色

  • Target(目標介面):客戶端期望的介面
  • Adaptee(被適配者):現有、介面不相容的類
  • Adapter(適配器):實現 Target,內部委派/繼承 Adaptee,完成介面轉換

形式一:類適配器(多重繼承模擬)

C# 不支援類多重繼承,但可實現多個介面並繼承單一類。類適配器繼承 Adaptee、實現 Target:


// 目標介面
public interface ITarget {
    void Operation1(); // 現有方法
    void Operation2(); // 新增方法
}

// 被適配者(現有類)
public class Adaptee {
    public void Operation1() {
        Console.WriteLine("Adaptee.Operation1");
    }
}

// 類適配器:繼承 Adaptee + 實現 ITarget
public class ClassAdapter : Adaptee, ITarget {
    // Operation1 直接繼承自 Adaptee

    // 實現 Target 獨有的 Operation2
    public void Operation2() {
        Console.WriteLine("ClassAdapter.Operation2 (轉換邏輯)");
    }
}

// 客戶端使用
public class Client {
    public void Use(ITarget target) {
        target.Operation1();
        target.Operation2();
    }
}

// 測試
var adapter = new ClassAdapter();
new Client().Use(adapter);
// 輸出:
// Adaptee.Operation1
// ClassAdapter.Operation2 (轉換邏輯)

類適配器特性

優點缺點
可覆寫 Adaptee 的虛擬方法(Override)C# 單一繼承限制:無法適配 Adaptee 及其子類(需為每個子類寫適配器)
結構簡單,單一類完成違反「組合優於繼承」原則,耦合度高
無額外委派開銷適配器即 Adaptee 子類,型別爆炸風險

形式二:物件適配器(組合/委派)

適配器持有 Adaptee 參考,實現 Target 介面,將呼叫委派給 Adaptee:


// 物件適配器
public class ObjectAdapter : ITarget {
    private readonly Adaptee _adaptee;

    public ObjectAdapter(Adaptee adaptee) {
        _adaptee = adaptee ?? throw new ArgumentNullException(nameof(adaptee));
    }

    public void Operation1() {
        _adaptee.Operation1(); // 委派
    }

    public void Operation2() {
        Console.WriteLine("ObjectAdapter.Operation2 (轉換邏輯)");
    }
}

// 使用:可適配 Adaptee 及其任意子類
var adaptee = new Adaptee();
var adapter = new ObjectAdapter(adaptee);
new Client().Use(adapter);

// 甚至適配子類
public class SubAdaptee : Adaptee {
    public void SpecialMethod() { }
}
var subAdapter = new ObjectAdapter(new SubAdaptee()); // 同一適配器類

物件適配器特性

優點缺點
一個適配器適配 Adaptee 及所有子類需額外委派呼叫(微小效能開銷)
符合組合優於繼承,低耦合難以覆寫 Adaptee 方法(需先建立子類再適配)
執行期可動態切換被適配物件結構稍複雜

深度對比與選擇指南

決策維度選擇類適配器選擇物件適配器
被適配類階層單一類、無子類、或不需適配子類類族、需統一適配多個子類
方法覆寫需求需覆寫 Adaptee 虛擬方法無覆寫需求,或可接受建立子類
耦合度容忍可接受緊耦合追求鬆耦合、可測試性
C# 語言限制利用「類繼承+介面實現」模擬多重繼承純介面導向,無繼承限制
現代 C# 偏好罕用推薦(符合 SOLID 原則)

實戰變體:雙向適配器與預設介面方法

雙向適配器

適配器同時實現 Target 與 Adaptee 介面,可在兩種上下文流通:


public interface ITarget { void Request(); }
public interface IAdaptee { void SpecificRequest(); }

public class TwoWayAdapter : ITarget, IAdaptee {
    private readonly Adaptee _adaptee = new Adaptee();

    public void Request() => _adaptee.SpecificRequest();
    public void SpecificRequest() => _adaptee.SpecificRequest();
}

C# 8.0+ 預設介面方法(減輕適配器樣板代碼)


public interface ITarget {
    void Operation1();
    void Operation2() => Console.WriteLine("Target 預設 Operation2"); // 預設實現
}

public class Adapter : Adaptee, ITarget {
    // 僅需實現 Operation1(若 Adaptee 無則自行實現)
    // Operation2 直接用介面預設實現,無須在適配器中寫代碼
}

經典應用場景

  1. 第三方庫整合:將外部 API 包裝為內部領域介面
  2. 舊系統遷移:新系統定義 Target,適配器包裝舊類
  3. 資料庫驅動:IDbConnection 適配各廠商具體連線類
  4. UI 控制項包裝:統一不同廠商 Grid 控制項介面
  5. 測試替身:適配真實服務為可控的 Mock 介面

總結

適配器模式以「介面轉換」解決相容性難題。C# 語言特性(單一繼承、多介面實現、預設介面方法)深刻影響了兩種形式的實現方式與取捨。物件適配器(組合)是現代 C# 開發的首選,符合依賴倒置、開閉原則,支援動態組合與測試替換。類適配器僅在需覆寫被適配者行為、且被適配者為單一密封類時考慮。掌握兩者本質差異,能在重構、整合、遷移等場景做出最優架構決策。

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