設計模式之適配器模式

0x01.定義和類型

  • 定義:將一個類的接口轉換成客戶指望的另外一個接口,適配器模式讓那些不兼容的類能夠一塊兒工做。
  • 類型:結構型

a.類適配器模式

  • 類適配器模式:使用繼承的方式去實現接口適配。
  • UML:

clipboard.png

  • Java實現
/**
 * 客戶須要的接口
 */
public interface Target {
    void request();
}

/**
 * 被適配的類
 */
public class Adaptee {
    public void adapteeRequest () {
        System.out.println("被適配者的方法");
    }
}

/**
 * 適配器,繼承了被適配的類,而且實現了Target定義的接口
 */
public class Adapter extends Adaptee implements Target {
    @Override
    public void request() {
        //todo...
        System.out.println("適配後----");
        super.adapteeRequest();
        //todo...
    }
}
  • 測試與應用
/**
 * 測試類
 */
public class Test {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        adaptee.adapteeRequest();

        Target adapterTarget = new Adapter();
        adapterTarget.request();
    }
}
  • 輸出結果
被適配者的方法
適配後----
被適配者的方法

b.對象適配器模式

  • 對象適配器模式:使用組合的方式去實現接口適配
  • UML

clipboard.png

  • Java實現
/**
 * 客戶端應用放使用的接口
 */
public interface Target {
    void request();
}

/**
 * 被適配的類
 */
public class Adaptee {
    public void adapteeRequest () {
        System.out.println("被適配者的方法");
    }
}

/**
 * 適配器模式
 */
public class Adapter implements Target {

    /**
     * 組合了被適配的類,這裏能夠經過set方式注入
     */
    private Adaptee adaptee = new Adaptee();

    @Override
    public void request() {
        //todo...
        System.out.println("適配後----");
        adaptee.adapteeRequest();
        //todo...
    }
}
  • 應用與測試類
/**
 * 應用測試類
 */
public class Test {

    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        adaptee.adapteeRequest();

        Target adapterTarget = new Adapter();
        adapterTarget.request();
    }
}
  • 輸入結果
被適配者的方法
適配後----
被適配者的方法

c.角色介紹

  • 從上面兩種狀況能夠看出,適配器模式一共有三個角色html

    • Target(目標抽象類):目標抽象類定義客戶所需的接口,能夠是一個抽象類或接口,也能夠是具體類。
    • Adapter(適配器類):它能夠調用另外一個接口,做爲一個轉換器,對Adaptee和Target進行適配。它是適配器模式的核心。
    • Adaptee(適配者類):適配者即被適配的角色,它定義了一個已經存在的接口,這個接口須要適配,適配者類包好了客戶但願的業務方法。

0x02.適用場景

  • 已經存在的類,它的方法和需求不匹配時(方法結果相同或類似)
  • 建立一個能夠重複使用的類,用於和一些彼此之間沒有太大關聯的類,包括一些可能在未來引進的類一塊兒工做
  • 適配器模式不是軟件設計階段考慮的設計模式,是隨着軟件維護,因爲不一樣產品,不一樣廠家形成功能相似而接口不相同狀況下的解決方案。

0x03.優勢

  • 能提升類的透明性和複用,將具體的業務實現過程封裝在適配者類中,對於客戶端類而言是透明的,現有的類複用但不須要改變,並且提升了適配者的複用性,同一適配者類能夠在多個不一樣的系統中複用。
  • 目標類和適配器類解耦,經過引入一個適配器類來重用現有的適配者類,無需修改原有結構,提升程序擴展性。
  • 靈活性和擴展性都很是好,經過使用配置文件,能夠很方便的更換適配器,也能夠在不修改原有代碼的基礎上,增長新的適配器,符合開閉原則。

0x04.缺點

  • 適配器編寫過程須要全面考慮,可能會增長系統的複雜性。
  • 一次最多隻能適配一個適配者類,不能同時適配多個適配者。
  • 增長系統代碼可讀的難度。

0x05. 樣例實現

筆記本的插頭爲三項電,而現有的插座是兩項的,須要適配器來進行適配,下面分別進行兩種方式的實現。
  • 通用代碼
/**
 * 三項插座接口
 * @author Administrator
 *
 */
public interface ThreePlugIf {
    //使用三項電流供電
    void powerWithThree();
}

/**
 * 二項電插座
 */
public class GBTowPlug {
    //使用二項電流供電
    public void powerWithTwo () {
        System.out.println("使用二項電流供電");
    }
}

/**
 * 筆記本類
 */
public class NoteBook {

    private ThreePlugIf plug;

    /**
     * 只接收使用三項電充電
     * @param plug
     */
    public NoteBook (ThreePlugIf plug) {
        this.plug = plug;
    }

    /**
     * 使用插座充電
     */
    public void charge () {
        plug.powerWithThree();
    }
}

a.類適配器的實現

  • 具體Java代碼
/**
 * 採用繼承方式的插座適配器
 * @author Administrator
 */
public class TwoPlugAdapterExtends extends GBTowPlug implements ThreePlugIf {

    public void powerWithThree() {
        System.out.println("藉助繼承適配器");
        this.powerWithTwo();
    }
}
  • 測試與應用類
/**
 * 測試與應用類
 */
public class AdapterTest {

    public static void main(String[] args) {
        ThreePlugIf three = new TwoPlugAdapterExtends();
        NoteBook book = new NoteBook(three);
        book.charge();
    }
}
  • 輸出結果
藉助繼承適配器
使用二項電流供電
  • 樣例UML類圖:

clipboard.png

b.對象適配器的實現

  • 具體Java代碼
/**
 * 二項插座轉三項插座的適配器
 */
public class TwoPlugAdapter implements ThreePlugIf {

    /**
    * 組合
    */
    private GBTowPlug plug;

    public TwoPlugAdapter (GBTowPlug plug) {
        this.plug = plug;
    }

    public void powerWithThree() {
        System.out.println("經過轉化");
        plug.powerWithTwo();
    }
}
  • 測試與應用類
/**
 * 測試與應用類
 */
public class AdapterTest {
    public static void main(String[] args) {
        GBTowPlug two = new GBTowPlug();
        ThreePlugIf three = new TwoPlugAdapter(two);
        NoteBook book = new NoteBook(three);
        book.charge();
    }
}
  • 輸出結果
對象適配器-經過轉化
使用二項電流供電
  • 樣例UML類圖:

clipboard.png

0x06.相關設計模式

  • 適配器模式和外觀模式java

    • 對現有的類現存系統的封裝
    • 外觀:定義了新的接口,建立新的接口對現有接口的封裝
    • 適配器:複用原有的接口,使兩個已有的接口協同工做
    • 兩種:適配的力度不一樣,外觀針對的力度更大

0x07.源碼中的適配器

  • JDK: XmlAdapter
  • Spring AOP: AdvisorAdapter, MethodBeforeAdvice
  • Spring Data JPA: JpaVendorAdapter
  • Spring MVC: Handler Adacpter

0x08.源碼地址

0x09.參考

相關文章
相關標籤/搜索