適配器模式 原

適配器模式

    適配器模式(Adapter Pattern)是作爲兩個不兼容的接口之間的橋樑。這種類型的設計模式屬於結構型模式,它結合了兩個獨立接口的功能。這種模式涉及到一個單一的類,該類負責加入獨立的或不兼容的接口功能。舉個真實的例子,讀卡器是作爲內存卡和筆記本之間的適配器。您將內存卡插入讀卡器,再將讀卡器插入筆記本,這樣就可以通過筆記本來讀取內存卡。

介紹

意圖:將一個類的接口轉換成客戶希望的另外一個接口。適配器模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。

主要解決:主要解決在軟件系統中,常常要將一些"現存的對象"放到新的環境中,而新環境要求的接口是現對象不能滿足的。

何時使用: 1、系統需要使用現有的類,而此類的接口不符合系統的需要。 2、想要建立一個可以重複使用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作,這些源類不一定有一致的接口。 3、通過接口轉換,將一個類插入另一個類系中。(比如老虎和飛禽,現在多了一個飛虎,在不增加實體的需求下,增加一個適配器,在裏面包容一個虎對象,實現飛的接口。)

如何解決:繼承或依賴(推薦)。

關鍵代碼:適配器繼承或依賴已有的對象,實現想要的目標接口。

應用實例: 1、美國電器 110V,中國 220V,就要有一個適配器將 110V 轉化爲 220V。 2、JAVA JDK 1.1 提供了 Enumeration 接口,而在 1.2 中提供了 Iterator 接口,想要使用 1.2 的 JDK,則要將以前系統的 Enumeration 接口轉化爲 Iterator 接口,這時就需要適配器模式。 3、在 LINUX 上運行 WINDOWS 程序。 4、JAVA 中的 jdbc。

優點: 1、可以讓任何兩個沒有關聯的類一起運行。 2、提高了類的複用。 3、增加了類的透明度。 4、靈活性好。

缺點: 1、過多地使用適配器,會讓系統非常零亂,不易整體進行把握。比如,明明看到調用的是 A 接口,其實內部被適配成了 B 接口的實現,一個系統如果太多出現這種情況,無異於一場災難。因此如果不是很有必要,可以不使用適配器,而是直接對系統進行重構。 2.由於 JAVA 至多繼承一個類,所以至多隻能適配一個適配者類,而且目標類必須是抽象類。

使用場景:有動機地修改一個正常運行的系統的接口,這時應該考慮使用適配器模式。

注意事項:適配器不是在詳細設計時添加的,而是解決正在服役的項目的問題。

個人理解 : 適配器模式是爲了給我們解決目前系統在用的接口當中數據不匹配問題設計的,例如當我們調用一個接口的數據與我們需要的類型不符合的時候我們可以使用適配器模式來做一個轉換,將當前接口的數據類型返回成我們需要的數據類型。我們也可以這樣理解:當我們爲了完成一個功能需要調用一個接口A的時候發現我們需要的一個方法在接口B中存在,我們這個時候不能修改接口A去實現B中的方法,這時候我們可以寫一個適配器來通過適配器完成調用接口A的時候完成對接口B中方法的調用。

實現

類適配器

    如下實現的是一個類適配器模式,所謂的類適配器模式就是通過繼承來實現適配。

    下面代碼中有個蘋果接口和USB接口以及蘋果接口的實現類和USB接口的實現類,我們一般情況的使用某個接口充電就會直接使用這個接口的實例,例如我們如果想用安卓接口就會Usb usb = new Usber();然後通過實例調用usb接口方法就可以了,但是我們如果這時候拿的是一個蘋果手機,但是沒有蘋果充電線(下面代碼中若沒有蘋果接口實現類),這個時候我們需要一個轉換器讓我們使用安卓充電口也可以爲蘋果手機充電。於是我們便寫了適配器Adapter作一個接口的轉換。

    下面適配器類Adapter繼承了Usber類(該類實現了Usb接口)並實現了Lighting接口與接口中的useLightning()方法,這樣通過Lighting接口獲取的實例就可以調用Usb接口的實現類中的方法了。想這種適配器通過繼承接口的實現類的完成適配的方式就是類適配器。

/**
 * 蘋果接口
 */
public interface Lightning {
    void useLightning();
}

/**
 * 安卓USB接口
 */
public interface Usb {
    void useUsb();
}

/**
 * 安卓接口實現類
 */
public class Usber implements Usb{
    @Override
    public void useUsb() {
        System.out.println("使用usb接口");
    }
}

/**
 * 蘋果接口實現類
 */
public class Lightninger implements Lightning{
    @Override
    public void useLightning() {
        System.out.println("使用蘋果接口");
    }
}


/**
 * 適配器
 */
public class Adapter extends Usber implements Lightning{

    @Override
    public void useLightning() {
        useUsb();
    }
}

/**
 * 實現類
 */
public class Client {
    public static void main(String[] args) {
        Lightning lightning = new Adapter();
        lightning.useLightning();
    }
}

 

對象適配器

    對象適配器和類適配器沒有什麼太大的區別,它們的充電接口以及實現類完全一樣,區別在於適配器類的實現形式和Client中對適配器的調用方式。對象適配器不需要適配器類(Adapter類)去繼承需要適配的接口的實現類。我們在對象適配器中只需要讓適配器類實現需要被適配的接口,並在適配器內實現一個新的構造函數去動態獲取需要調用實現類的實例對象便可以。

/**
 * 蘋果接口
 */
public interface Lightning {
    void useLightning();
}

/**
 * 安卓USB接口
 */
public interface Usb {
    void useUsb();
}

/**
 * 安卓接口實現類
 */
public class Usber implements Usb{
    @Override
    public void useUsb() {
        System.out.println("使用usb接口");
    }
}

/**
 * 蘋果接口實現類
 */
public class Lightninger implements Lightning{
    @Override
    public void useLightning() {
        System.out.println("使用蘋果接口");
    }
}

/**
 * 適配器
 */
public class Adapter implements Lightning{

    private Usb usb;

    public Adapter(Usb usb) {
        this.usb = usb;
    }

    @Override
    public void useLightning() {
        usb.useUsb();
    }
}

/**
 * 實現類
 */
public class Client {
    public static void main(String[] args) {
        Lightning lightning = new Adapter(new Usber());
        lightning.useLightning();
    }
}

 

接口適配器

    如下代碼實現了一個基本的接口適配器,我們需要實現球類接口中足球好籃球的方法。接口適配器的使用場景是當一個接口當中有過多的方法,而我們只需要實現其中的一個或者幾個方法的時候使用,因爲我們如果實現一個接口的話那麼要實現這個接口當中所有的方法,這樣寫着是比較麻煩的,這個時候我們就可以使用接口適配器,通過讓抽象類Baller去實現Ball接口,然後讓我們的適配器去繼承抽象類並實現足球和籃球的方法,這樣在測試類Client中便可以通過Ball接口獲取適配器類的實例調用足球和籃球方法了。

/**
 * 球類接口
 */
public interface Ball {

    void basketball();

    void football();

    void baseball();

    void volleyball();
}

/**
 * 抽象類
 */
public abstract class Baller implements Ball {
    public void basketball() {}

    public void football() {}

    public void baseball() {}

    public void volleyball() {}
}

/**
 * 適配器
 */
public class Adapter extends Baller{

    public void basketball() {
        System.out.println("籃球");
    }

    public void football() {
        System.out.println("足球");
    }
}

/**
 * 實現類
 */
public class Client {
    public static void main(String[] args) {
        Ball ball = new Adapter();
        ball.basketball();
        ball.football();
    }
}

 

    三種適配器模式都有各自的特點,類適配器和對象適配器基本相同,只不過區別在於是否存在繼承關係,一般建議使用對象適配器,因爲java裏面不支持多繼承,一般不要隨意地去繼承一個類。接口適配器和前面兩個適配器所解決的問題不一樣,接口適配器是爲了解決需要實現的接口當中沒用的方法較多的情況。

參考網址:http://www.runoob.com/design-pattern/adapter-pattern.html

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