[設計模式] - No.5 Adapter模式
Adapter模式
1. 什麼是Adapter模式
Adapter
模式中文名稱叫介面卡模式,就像我們的電腦電源介面卡將直流電源轉換為交流電源一樣,介面卡模式可以將我們現有的某些已經具備相關類,轉換為我們需要的型別。Adapter
模式又稱為Wrapper
模式,相信這個名詞很多做過Java Web
專案的同學並不陌生。當我們從資料庫中查詢出來的資料雖然具備了我們需要的一些欄位,但是並不能直接被某些介面使用的時候,我們需要使用Wrapper
對資料進行轉換。
Adapter
模式具有兩種實現方式:
- 類介面卡模式(使用繼承)
- 物件介面卡模式(使用委託)
在下邊,我將結合書中的程式碼示例來解釋兩種模式,並探究在什麼情況下,需要使用哪種方式。
2. 使用繼承方式的類介面卡模式
假設我們的在上層介面需要呼叫一個(實現)Print
型別的物件,來完成列印橫幅的功能,而我們下層的程式碼中,只有一個Banner
的類,完成了列印橫幅的功能,那麼怎麼樣才能順利的實現列印橫幅的功能呢?這時候,我們就要使用介面卡模式,構建一箇中間體,他具備了(實現)Print
介面,又可以基於現有的類,列印橫幅。
Print.java
public interface Print {
void printWeak();
void printStrong();
}
Banner.java
public class Banner {
private String banner;
public Banner(String banner) {
this.banner = banner;
}
public void showWithParen(){
System.out.println("(" + banner + ")");
}
public void showWithAster(){
System.out.println("*" + banner + "*");
}
}
PrintBanner.java
public class PrintBanner extends Banner implements Print {
public PrintBanner(String banner) {
super(banner);
}
@Override
public void printWeak() {
showWithParen();
}
@Override
public void printStrong() {
showWithAster();
}
}
Main.java
public class Main {
public static void main(String args []){
Print p = new PrintBanner("橫幅內容");
p.printWeak();
p.printStrong();
}
}
控制檯輸出內容:
(橫幅內容)
*橫幅內容*
我們創造了PrintBanner
這樣一箇中間體,既滿足了Print
介面,又很好地實現了列印的功能,這就是最典型的的介面卡模式。
如果我們對上層介面做一些改變,它不再依賴Print
interface
,而是需要一個Print
的類該怎麼辦呢?
即Print
更改為抽象類的形式
public abstract class Print {
abstract void printWeak();
abstract void printStrong();
}
對應的PrintBanner
也要做相應的改變。但是由於在java
中,一個類可以實現很多的介面,但是隻能繼承自一個父類,所以我們需要重新規劃PrintBanner
的內部實現:
public class PrintBanner extends Print {
private Banner banner;
public PrintBanner(String banner) {
this.banner = new Banner(banner);
}
@Override
public void printWeak() {
banner.showWithParen();
}
@Override
public void printStrong() {
banner.showWithAster();
}
}
如上面所示,我們讓PrintBanner
繼承自抽象類Print
,其內部包含了一個Banner
型別的成員變數,在我們實現printWeak
和printStrong
時,我們讓這個變數呼叫相應的列印函式來完成這個功能,這就是一個很好的基於委託方式的介面卡模式的小例子。
3. Adapter模式中的各種角色:
由上面的程式碼,我們可以清晰的看到,在這種設計模式中,由四個角色:
-
Target(物件)
該角色負責定義上層介面所需要的方法,例如本例子中的
Print
類/介面, -
Client(請求者)
這也就是我們上文提到的上層介面。該角色負責呼叫
Target
物件對應的方法來完成對應的功能。這個例子中的Main
就是我們的請求者 -
Adaptee
被適配的類,通常是我們所擁有的某個已經實現好的類,但是型別上不符合上層介面的需要。本例中的
Banner
就是這個角色。 -
Adapter(介面卡)
這個是介面卡模式最重要的一部分,它主要是使用
Adaptee
中現有的方法,來滿足Target
角色的需求。按照Target
的型別(class/interface
),又具體分為繼承方式和委託方式來實現。兩種方式的類圖如下所示:
-
當我們的需求是一個
class
型別的時候,我們需要使用委託的方式。 -
當我們的需求是一個
interface
型別的時候,我們需要使用繼承的方式。