結構型模式-適配器模式(不兼容結構的協調)

與電源適配器類似,在適配器模式中引入了一個被稱爲適配器(Adapter)的包裝類,而它所包裝的對象稱爲適配者(Adaptee),即被適配的類。適配器的實現就是把客戶類的請求轉化爲對適配者的相應接口的調用。也就是說:當客戶類調用適配器的方法時,在適配器類的內部將調用適配者類的方法,而這個過程對客戶類是透明的,客戶類並不直接訪問適配者類。所以,適配器讓那些因爲接口不兼容而不能交互的類能夠一塊兒工做。
適配器模式能夠將一個類的接口和另外一個類的接口匹配起來,而無須修改原來的適配者接口和抽象目標類接口,它是一種使用頻率很是高的設計模式,在軟件開發中得以普遍應用,在Spring等開源框架、驅動程序設計(如JDBC中的數據庫驅動程序)中也使用了適配器模式git

1. 定義

適配器模式(Adapter Pattern):將一個接口轉換成客戶但願的另外一個接口,使接口不兼容的那些類能夠一塊兒工做,其別名爲包裝器(Wrapper)。適配器模式既能夠做爲類結構型模式,也能夠做爲對象結構型模式。數據庫

2. 結構

在適配器模式中,咱們經過增長一個新的適配器類來解決接口不兼容的問題,使得本來沒有任何關係的類能夠協同工做。根據適配器類與適配者類的關係不一樣,適配器模式可分爲對象適配器和類適配器兩種,在對象適配器模式中,適配器與適配者之間是關聯關係;在類適配器模式中,適配器與適配者之間是繼承(或實現)關係。在實際開發中,對象適配器的使用頻率更高,對象適配器模式結構如圖所示:編程

適配器模式

  • Target(目標抽象類):目標抽象類定義客戶所需接口,能夠是一個抽象類或接口,也能夠是具體類。
  • Adapter(適配器類):適配器能夠調用另外一個接口,做爲一個轉換器,對Adaptee和Target進行適配,適配器類是適配器模式的核心,在對象適配器中,它經過繼承Target並關聯一個Adaptee對象使兩者產生聯繫。
  • Adaptee(適配者類):適配者即被適配的角色,它定義了一個已經存在的接口,這個接口須要適配,適配者類通常是一個具體類,包含了客戶但願使用的業務方法,在某些狀況下可能沒有適配者類的源代碼。

3. 代碼實現

Target設計模式

public interface Home {
    void watchTv();
    void useFridge();
}

Adaptee1app

public class Haier {
    public void watchHaierTv(){
        System.out.println("看海爾電視啦");
    }
    public void userHaierFridge(){
        System.out.println("使用海爾冰箱啦");
    }
}

Adaptee2框架

public class Media {
    public void watchMediaTv(){
        System.out.println("看美的電視啦");
    }
    public void userMediaFridge(){
        System.out.println("使用美的冰箱啦");
    }
}

Adapter編程語言

public class HomeAdapter implements Home{
    private Haier haier;
    private Media media;

    public HomeAdapter() {
        this.haier = new Haier();
        this.media = new Media();
    }

    @Override
    public void watchTv() {
        haier.watchHaierTv();
    }

    @Override
    public void useFridge() {
        media.userMediaFridge();
    }
}

Testide

public class Test {

    public static void main(String[] args) {
        //這邊可以使用配置文件經過反射來得到具體的適配器
        Home home=new HomeAdapter();
        home.watchTv();
        home.useFridge();
    }
}
//看海爾電視啦
//使用美的冰箱啦

4. 類適配器,雙向適配器,缺省適配器

4.1 類適配器

類適配器模式和對象適配器模式最大的區別在於適配器和適配者之間的關係不一樣,對象適配器模式中適配器和適配者之間是關聯關係,而類適配器模式中適配器和適配者是繼承關係,代碼以下:this

class Adapter extends Adaptee implements Target {  
    public void request() {  
        specificRequest();  
    }  
}

因爲Java、C#等語言不支持多重類繼承,所以類適配器的使用受到不少限制,例如若是目標抽象類Target不是接口,而是一個類,就沒法使用類適配器;此外,若是適配者Adapter爲最終(Final)類,也沒法使用類適配器。在Java等面向對象編程語言中,大部分狀況下咱們使用的是對象適配器,類適配器較少使用。

4.2 雙向配器

在對象適配器的使用過程當中,若是在適配器中同時包含對目標類和適配者類的引用,適配者能夠經過它調用目標類中的方法,目標類也能夠經過它調用適配者類中的方法,那麼該適配器就是一個雙向適配器,代碼以下:

class Adapter implements Target,Adaptee {  
    //同時維持對抽象目標類和適配者的引用  
    private Target target;  
    private Adaptee adaptee;  

    public Adapter(Target target) {  
        this.target = target;  
    }  

    public Adapter(Adaptee adaptee) {  
        this.adaptee = adaptee;  
    }  

    public void request() {  
        adaptee.specificRequest();  
    }  

    public void specificRequest() {  
        target.request();  
    }  
}

平時開發不多使用雙向適配器。

4.3 缺省適配器

當不須要實現一個接口所提供的全部方法時,可先設計一個抽象類實現該接口,併爲接口中每一個方法提供一個默認實現(空方法),那麼該抽象類的子類能夠選擇性地覆蓋父類的某些方法來實現需求,它適用於不想使用一個接口中的全部方法的狀況,又稱爲單接口適配器模式,代碼以下:

抽象類中實現了一些接口方法做爲默認實現

public  abstract class AbstractHomeAdapter implements Home{

    protected Haier haier=new Haier();

    protected Media media=new Media();

    @Override
    //默認看海爾電視
    public void watchTv() {
        haier.watchHaierTv();
    }

    //默認使用美的冰箱
    @Override
    public void useFridge() {
        media.userMediaFridge();
    }
}

繼承該抽象類的子類可選擇性的覆蓋一些方法,其餘方法則使用父類的默認實現

public class OtherHomeAdapter extends AbstractHomeAdapter {

    @Override
    //重寫方法,其餘方法默認
    public void useFridge() {
        super.haier.userHaierFridge();
    }
}

5. 優缺點

  • 優勢
  1. 將目標類和適配者類解耦,經過引入一個適配器類來重用現有的適配者類,無須修改原有結構。
  2. 增長了類的透明性和複用性,將具體的業務實現過程封裝在適配者類中,對於客戶端類而言是透明的,並且提升了適配者的複用性,同一個適配者類能夠在多個不一樣的系統中複用。
  3. 靈活性和擴展性都很是好,經過使用配置文件,能夠很方便地更換適配器,也能夠在不修改原有代碼的基礎上增長新的適配器類,徹底符合「開閉原則」。
  • 缺點
  1. 對於類適配器來講,其使用具備必定侷限性

    (1)對於Java、C#等不支持多重類繼承的語言,一次最多隻能適配一個適配者類,不能同時適配多個適配者(只能繼承一個類,但能夠包含多個類);

    (2)適配者類不能爲最終類,如在Java中不能爲final類,C#中不能爲sealed類(最終類了就不能繼承了);

    (3)在Java、C#等語言中,類適配器模式中的目標抽象類只能爲接口,不能爲類(由於不能繼承2個類)。

  2. 對於對象適配器來講,與類適配器模式相比,要在適配器中置換適配者類的某些方法比較麻煩(修改原有的方法)。

6. 適用場景

  1. 系統須要使用一些現有的類,而這些類的接口(如方法名)不符合系統的須要,甚至沒有這些類的源代碼。
  2. 想建立一個能夠重複使用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在未來引進的類一塊兒工做。

7. 我的理解

適配器模式將現有接口轉化爲客戶類所指望的接口,實現了對現有類的複用。

參考

  1. Java設計模式-劉偉
相關文章
相關標籤/搜索