(精華)2020年8月28日 二十三種設計模式(六)-介面卡模式(Adapter Pattern)

愚公搬程式碼發表於2020-08-13

介面卡模式(Adapter Pattern)

介面卡模式屬於結構型模式,把一個類的介面變成客戶端所期待的另一種介面,從而使原本介面不匹配而無法一起工作的兩個類能夠在一起工作。

介面卡模式又可以分為4種型別,類介面卡模式、物件介面卡模式、單介面介面卡模式(預設介面卡模式)和雙向介面卡模式。後2種模式的實現比較複雜並且在實際開發過程中很少使用,故本博文只討論前2種模式。

角色

1、抽象目標(Target)

抽象目標類定義客戶所需的介面,可以是一個抽象類或介面,也可以是具體類。在類介面卡中,由於C#語言不支援多重繼承,所以它只能是介面;

2、介面卡(Adapter)

它可以呼叫另一個介面,作為一個轉換器,對Adaptee和Target進行適配,它是介面卡模式的核心;

3、適配者(Adaptee)

適配者即被適配的角色,它定義了一個已經存在的介面,這個介面需要適配,適配者類包好了客戶希望的業務方法。

示例

在這裡插入圖片描述
名稱空間AdapterPattern包含ClassBased和ObjectBased子名稱空間,分別表示基於類的介面卡模式和基於物件的介面卡模式。類的介面卡中包含家用電器類、電壓類、目標動作介面和手機介面卡類。物件的介面卡中包含適配者、介面卡、目標介面和目標基類。本案例嘗試使用手機介面卡將家用電器的電壓從220V適配至3V。

namespace AdapterPattern

類的介面卡模式

namespace AdapterPattern.ClassBased
public class Voltage {

    public uint Value { get; set; }

}

電壓Voltage類,包含一個無符號int型別的電壓值。

public class Appliance {

    public Voltage GetVoltage() {
        return new Voltage { Value = 220 };
    }

}

家用電器Appliance類,包含一個獲取電壓的GetVoltage方法。

public interface ITarget {

    Voltage GetMobileVoltage();

}

目標介面ITarget,包含一個獲取手機電壓的GetMobileVoltage方法。這是我們要適配的目標動作。

public class MobileAdapter : Appliance, ITarget {
 
    public Voltage GetMobileVoltage() {
        var voltage = GetVoltage();
        Console.WriteLine($"Appliance voltage is {voltage.Value}V!");
 
        voltage.Value = 3;
        Console.WriteLine($"After adapted,it becomes {voltage.Value}V!");
 
        return voltage;
    }
 
}

手機介面卡MobileAdapter類,繼承自Applicance家用電器並實現ITarget介面。

物件的介面卡模式

namespace AdapterPattern.ObjectBased
public class Adaptee {

    public void OriginalMethod() {
        Console.WriteLine("Original Method is being called!");
    }

}

適配者Adaptee類,這是將要被我們適配的類。

public interface ITarget {

    void TargetMethod();

}

目標介面ITarget,定義我們的目標動作。

public class Target : ITarget {

    public virtual void TargetMethod() {
        Console.WriteLine("Target Method is being called!");
    }

}

目標Target類,實現目標介面以實現動作。

public class Adapter : Target {

    private Adaptee _adaptee = new Adaptee();

    public override void TargetMethod() {
        _adaptee.OriginalMethod();
    }

}

介面卡Adapter類,繼承自Target類。內部維持對適配者的引用並實現一個目標動作。

public class Program {

    private static ClassBased.ITarget _targetClass = null;
    private static ObjectBased.ITarget _targetObject = null;

    public static void Main(string[] args) {
        //Class Pattern
        _targetClass = new ClassBased.MobileAdapter();
        var voltage = _targetClass.GetMobileVoltage();

        Console.WriteLine("-----------------------------");

        //Object Pattern
        _targetObject = new ObjectBased.Adapter();
        _targetObject.TargetMethod();

        Console.ReadKey();
    }

}

以上是呼叫方的程式碼,分別演示了類的介面卡模式和物件的介面卡模式的用法。以下是這2個案例的輸出結果:

Appliance voltage is 220V!
After adapted,it becomes 3V!
-----------------------------
Original Method is being called!

優點

1、可以讓任何兩個沒有關聯的類一起執行;
2、可以在不修改原有程式碼的基礎上來複用現有類,很好地符合 “開閉原則”;
3、增加了類的透明度和更好的靈活性。

缺點

1、由於C#不支援多重繼承,所以最多隻能適配一個適配者類,而且目標類必須是抽象類;
2、採用了類和介面的“雙繼承”實現方式,帶來了不良的高耦合。

使用場景

1、系統需要複用現有類,而該類的介面不符合系統的需求;
2、想要建立一個可重複使用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作;
3、對於物件介面卡模式,在設計裡需要改變多個已有子類的介面,如果使用類的介面卡模式,就要針對每一個子類做一個介面卡,而這不太實際。

相關文章