結構型模式之介面卡模式
目錄
在現實生活中,經常出現兩個物件因介面不相容而不能在一起工作的例項,這時需要第三者進行適配。例如,用直流電的膝上型電腦接交流電源時需要一個電源介面卡。
在軟體設計中也可能出現:需要開發的具有某種業務功能的元件在現有的元件庫中已經存在,但它們與當前系統的介面規範不相容,如果重新開發這些元件成本又很高,這時用介面卡模式能很好地解決這些問題。
定義與特點
介面卡模式(Adapter)的定義如下:將一個類的介面轉換成客戶希望的另外一個介面,使得原本由於介面不相容而不能一起工作的那些類能一起工作。介面卡模式分為類結構型模式和物件結構型模式兩種,前者類之間的耦合度比後者高,且要求程式設計師瞭解現有元件庫中的相關元件的內部結構,所以應用相對較少些。
該模式的主要優點如下:
- 客戶端通過介面卡可以透明地呼叫目標介面。
- 複用了現存的類,程式設計師不需要修改原有程式碼而重用現有的適配者類。
- 將目標類和適配者類解耦,解決了目標類和適配者類介面不一致的問題。
其缺點是:對類介面卡來說,更換介面卡的實現過程比較複雜。
結構與實現
類介面卡模式可採用多重繼承方式實現,如 C++ 可定義一個介面卡類來同時繼承當前系統的業務介面和現有元件庫中已經存在的元件介面;C#、Java 不支援多繼承,但可以定義一個介面卡類來實現當前系統的業務介面,同時又繼承現有元件庫中已經存在的元件。
物件介面卡模式可釆用將現有元件庫中已經實現的元件引入介面卡類中,該類同時實現當前系統的業務介面。
模式的結構
介面卡模式(Adapter)包含以下主要角色:
- 目標(Target)介面:當前系統業務所期待的介面,它可以是抽象類或介面。
- 適配者(Adaptee)類:它是被訪問和適配的現存元件庫中的元件介面。
- 介面卡(Adapter)類:它是一個轉換器,通過繼承或引用適配者的物件,把適配者介面轉換成目標介面,讓客戶按目標介面的格式訪問適配者。
類介面卡模式的結構圖如圖所示:
物件介面卡模式的結構圖如圖所示:
模式的實現
類介面卡模式的程式碼如下:
//訪問類 public class Program { static void Main(string[] args) { //類介面卡模式 Console.WriteLine("類介面卡模式測試:"); ITarget target = new ClassAdapter(); target.Request(); Console.ReadLine(); } } //目標介面 public interface ITarget { void Request(); } //適配者類 public class Adaptee { public void SpecificRequest() { Console.WriteLine("適配者中的業務程式碼被呼叫!"); } } //類介面卡類 public class ClassAdapter : Adaptee,ITarget { public void Request() { SpecificRequest(); } }
程式的執行結果如下:
類介面卡模式測試:
適配者中的業務程式碼被呼叫!
物件介面卡模式的程式碼如下:
//訪問類
public class Program
{
static void Main(string[] args)
{
//介面卡模式
Console.WriteLine("類介面卡模式測試:");
Adaptee adaptee = new Adaptee();
ITarget target = new ObjectAdapter(adaptee);
target.Request();
Console.ReadLine();
}
}
//物件介面卡類
class ObjectAdapter : ITarget
{
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee)
{
this.adaptee=adaptee;
}
public void Request()
{
adaptee.SpecificRequest();
}
}
說明:物件介面卡模式中的“目標介面”和“適配者類”的程式碼同類介面卡模式一樣,只要修改介面卡類和客戶端的程式碼即可。
程式的執行結果如下:
類介面卡模式測試:
適配者中的業務程式碼被呼叫!
應用場景
介面卡模式(Adapter)通常適用於以下場景:
- 以前開發的系統存在滿足新系統功能需求的類,但其介面同新系統的介面不一致。
- 使用第三方提供的元件,但元件介面定義和自己要求的介面定義不同。
擴充套件:雙向介面卡模式
介面卡模式(Adapter)可擴充套件為雙向介面卡模式,雙向介面卡類既可以把適配者介面轉換成目標介面,也可以把目標介面轉換成適配者介面,其結構圖如圖所示:
程式碼如下:
//訪問類
public class Program
{
static void Main(string[] args)
{
//雙向介面卡模式
Console.WriteLine("類介面卡模式測試:");
ITwoWayTarget target = new TargetRealize();
ITwoWayAdaptee adaptee = new AdapteeRealize();
Console.WriteLine("目標通過雙向介面卡訪問適配者:");
ITwoWayTarget twoWayTarget = new TwoWayAdapter(adaptee);
twoWayTarget.Request();
Console.WriteLine("-------------------");
Console.WriteLine("適配者通過雙向介面卡訪問目標:");
ITwoWayAdaptee twoWayAdaptee = new TwoWayAdapter(target);
twoWayAdaptee.SpecificRequest();
Console.ReadLine();
}
}
///目標介面
public interface ITwoWayTarget
{
void Request();
}
//適配者介面
public interface ITwoWayAdaptee
{
void SpecificRequest();
}
//目標實現
public class TargetRealize :ITwoWayTarget
{
public void Request()
{
Console.WriteLine("目的碼被呼叫!");
}
}
//適配者實現
public class AdapteeRealize : ITwoWayAdaptee
{
public void SpecificRequest()
{
Console.WriteLine("適配者程式碼被呼叫!");
}
}
//雙向介面卡
public class TwoWayAdapter : ITwoWayTarget, ITwoWayAdaptee
{
private ITwoWayTarget target;
private ITwoWayAdaptee adaptee;
public TwoWayAdapter(ITwoWayTarget target)
{
this.target=target;
}
public TwoWayAdapter(ITwoWayAdaptee adaptee)
{
this.adaptee=adaptee;
}
public void Request()
{
adaptee.SpecificRequest();
}
public void SpecificRequest()
{
target.Request();
}
}