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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章