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
類型的時候,我們需要使用繼承的方式。