適配器模式

手機充電的電壓爲5V,而普通家用電的電壓爲220V,爲了解決這種電壓不兼容的問題,我們引入了電源適配器(俗稱充電器)。在軟件系統中,類與類,模塊與模塊之間也會出現類似不兼容的現象,這時我們需要引入適配器模式來解決這個問題。

與電源適配器相似,在適配器模式中引入了一個被稱爲適配器(Adapter)的包裝類,它相當於我們的手機充電器,而它所包裝的對象稱爲適配者(Adaptee),即被適配的類,它相當與我們家用的220V電。適配器的實現就是把客戶端的請求轉化爲對適配者的相應接口的調用。也就是說,當客戶類調用適配器的方法時,在適配器類內部將調用適配者類的方法,而這個過程對客戶類是透明的,客戶類並不直接訪問適配者類。因此,適配者讓那些由於接口不兼容而不能交互的類可以一起工作。

適配器模式可以將一個類的接口和另一個類的接口匹配起來,而無須修改原有的適配者接口和目標類接口。

適配器模式的定義如下:

適配器模式(Adapter Pattern):將一個接口轉換成客戶希望的另一個接口,使接口不兼容的那些類可以一起工作,其別名爲包裝器(Wrapper)。適配器模式既可以作爲類結構型模式,也可以作爲對象結構型模式。

注意:在適配器模式定義中所提及的接口是指廣義的接口,它可以表示一個方法或者方法的集合。

根據適配器類與適配者類的關係不同,適配器模式可以分爲對象適配器模式和類適配器模式兩種。在對象適配器模式中,適配器與適配者之間是關聯關係;在類適配器模式中,適配器與適配者之間是繼承(或實現)關係。在實際開發中,對象適配器模式使用的頻率更高,其UML圖如下:

適配器模式主要包括一下3個角色:

1.Target(目標抽象類):目標抽象類定義客戶所需接口,可以是一個抽象類或接口,也可以是具體類;

2.Adapter(適配器類):適配器可以調用另一個接口,作爲一個轉換器,對Adaptee和Target進行適配。適配器類是適配器模式的核心,在對象適配者模式中,它通過繼承Target並關聯一個Adaptee對象使二者產生聯繫;

3.Adaptee(適配者類):適配者即被適配的角色,它定義了一個已經存在的接口,這個接口需要適配,適配者類一般是一個具體類,包含客戶希望使用的業務方法,在某些情況下可能沒有適配者類的源代碼。

在對象適配器模式中,客戶端需要調用request()方法,而適配者類Adaptee沒有該方法,但是它所提供的specificRequest()方法卻是客戶端所需要的。爲了使客戶端能夠使用適配者類,需要提供一個包裝類Adapter,即適配器類。這個包裝類包裝了一個適配者的實例,從而將客戶端與適配者銜接起來,在適配器的request()方法中調用適配者的specificRequest()方法。因爲適配器類與適配者類是關聯關係(也可稱之爲委派關係),所以這種適配器模式稱爲對象適配器模式。其Java代碼實現如下:

/**
 * 目標類,客戶端需要調用原接口的類(此接口與適配者類的接口即具體功能實現的接口不兼容)
 */
public interface Target {

    //客戶需要調用的接口
    void request();
}
/**
 * 適配者類,客戶需要使用此類中的方法,但是此類中的方法與目標類的接口不兼容
 */
public class Adaptee {

    public void specificRequest() {
        System.out.println("客戶最終要使用此方法");
    }
}
/**
 * 適配器類,通過對Adaptee類中客戶需要使用的specificRequest方法的轉換,來爲客戶提供兼容的request接口
 */
public class Adapter implements Target {

    //維持一個對適配者對象的引用
    private Adaptee adaptee;

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

    @Override
    public void request() {
        //真正調用客戶端需要調用的方法
        adaptee.specificRequest();
    }
}
/**
 * 客戶端類
 */
public class Client {

    public static void main(String[] args) {
        //創建適配者對象
        Adaptee adaptee = new Adaptee();
        //創建客戶端需要調用的目標對象,並注入真正需要調用的方法的對象
        Target target = new Adapter(adaptee);
        //通過目標類調用方法,內部真正調用的適配者對象的方法
        target.request();
    }
}

適配器模式的主要優點如下:

1.將目標類與適配者類解耦,通過引入一個適配器類來重用現有的適配者類,無須修改原有結構;

2.增加了類的透明性和複用性,將具體的業務實現過程封裝在適配者類中,對於客戶端類而言是透明的,而且提高了適配者類的複用性,同一個適配者類可以在多個不同的系統中複用;

3.靈活性和擴展性都非常好,通過使用配置文件,可以很方便地更換適配器,也可以在不修改原有代碼的基礎上增加新的適配器類,完全符合開閉原則。

適配器模式的主要缺點如下:

要在適配器中置換適配者類的某些方法比較麻煩。如果一定要置換掉適配者類的一個或多個方法,可以先做一個適配者類的子類,在子類中將適配者類的方法置換掉,然後再把適配者類的子類當作真正的適配者進行適配,實現過程較爲複雜。

適配器模式的適用場景如下:

1.系統需要使用一些現有的類,而這些類的接口(例如方法名)不符合系統的需要,甚至沒有這些類的源代碼;

2.想創建一個可以重複使用的類,用於與一些彼此之間沒有太大關聯的類,包括一些可能在將來引進的類一起工作。

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