Adapter模式
引言
生活中有很多Adapter的例子。比方說,你買了一款舒适、手感極佳的鍵盤,它是P/S接口的,然而你的新式電腦已經淘汰了P/S接口,隻提供USB接口。此時,為了能夠使用這款鍵盤,就需要一個轉接頭,它的一頭是P/S接口的,用來連接配接鍵盤;另一頭是USB的,用來連接配接電腦。類似這樣的轉接頭就充當一個Adapter的作用。類似的例子還有電源的三相/兩相 轉接頭等等。
Adapter模式應該是設計模式中一個輕量級的模式,實作起來也比較簡單,有時候不經意中,你可能就已經實作了一個Adapter模式,隻是自己沒有發現而已。本文将通過一個範例介紹 Adapter模式。
Shape範例
很多程式設計的書籍中都喜歡使用一個Shape作為範例講述面向對象中的繼承,盡管這裡我們講述的是Adapter模式,但是并不妨礙我們也使用這個Shape的例子。考慮下面一幅關系圖:

在這幅圖中,Shape抽象類定義了Draw()方法,用于在螢幕上繪制圖形,Square和Circle繼承了Shape類,并實作了Draw()方法。另一個與Shape相關聯的類Window,它的Initialize()方法接受一個Shape類型的參數,并調用其Draw()方法(實際中還可能進行其他操作,這裡的關鍵是方法的簽名隻接受一個Shape類型的參數)。
public void Initialize(Shape s)
現在考慮這樣一種情況:假如我們從第三方獲得了另一個類XTriangle,而它并沒有Draw()方法,隻有一個完成同樣功能的Display()方法。很顯然,這個類也不會繼承自Shape基類,我們也無法對其進行修改。此時。如果我們想讓客戶程式Window類使用XTriangle類,就不得不再重載一個Initialize()方法,讓它接受一個XTriangle類型的參數。但這是治标不治本的方法,因為可能有很多類似Window的類,它們都隻接受Shape類型,對每一處都進行修改顯然是不切實際的。此時,通常的辦法是建立一個包裝(Wrapper)類,讓這個包裝類繼承自Shape,同時讓它含有一個對XTriangle的引用,并且将Draw()方法的實作委托給XTriangle.Display()去完成。我們将這個包裝類命名為Triangle,而這種模式或者解決類似問題的方法,就稱為Adapter模式。注意在很多情況下我們會将Triangle命名為TriangleAdapter,但這裡命名為Triangle會更清晰一些,但它仍是一個Adapter。下面是類圖:
接下來我們看下來看一下Triangle的實作:
public class Triangle : Shape {
private XTriangle triangle;
public Triangle(XTriangle triangle) {
this.triangle = triangle;
}
public override void Draw() {
triangle.Display();
}
OK,這樣就實作了Adapter模式,它的正式定義是:
将一個類(XTriangle)的接口轉換為用戶端(Window)所期待的另一接口(Shape)。Adpater能夠讓各個類之間互相協作,而不受不相容接口的影響。總結
這篇文章通過一個簡短的範例示範了Adatper模式,通過建立一個包裝類,解決了在引入第三方類時接口不相容的問題。感謝閱讀,希望這篇文章能給你帶來幫助。