1. 程式人生 > >[設計模式] - No.5 Adapter模式

[設計模式] - 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型別的成員變數,在我們實現printWeakprintStrong時,我們讓這個變數呼叫相應的列印函式來完成這個功能,這就是一個很好的基於委託方式的介面卡模式的小例子。

3. Adapter模式中的各種角色:

由上面的程式碼,我們可以清晰的看到,在這種設計模式中,由四個角色:

  • Target(物件)

    該角色負責定義上層介面所需要的方法,例如本例子中的Print類/介面,

  • Client(請求者)

    這也就是我們上文提到的上層介面。該角色負責呼叫Target 物件對應的方法來完成對應的功能。這個例子中的Main 就是我們的請求者

  • Adaptee

    被適配的類,通常是我們所擁有的某個已經實現好的類,但是型別上不符合上層介面的需要。本例中的Banner就是這個角色。

  • Adapter(介面卡)

    這個是介面卡模式最重要的一部分,它主要是使用Adaptee中現有的方法,來滿足Target角色的需求。按照Target的型別(class/interface),又具體分為繼承方式和委託方式來實現。兩種方式的類圖如下所示:

在這裡插入圖片描述

  • 當我們的需求是一個class型別的時候,我們需要使用委託的方式。

  • 當我們的需求是一個interface型別的時候,我們需要使用繼承的方式。