適配器模式

描述

????適配器模式把一個(gè)類(lèi)的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無(wú)法在一起工作的兩個(gè)類(lèi)能夠在一起工作。

簡(jiǎn)介

????適配器模式有類(lèi)的適配器模式和對(duì)象的適配器模式兩種不同的形式。


類(lèi)適配器模式

????類(lèi)的適配器模式通過(guò)繼承方式把適配的類(lèi)的API轉(zhuǎn)換成為目標(biāo)類(lèi)的API。Adapter與Adaptee是繼承關(guān)系。


對(duì)象適配器模式

????對(duì)象的適配器模式通過(guò)組合方式把適配的類(lèi)的API轉(zhuǎn)換成為目標(biāo)類(lèi)的API。Adapter與Adaptee是組合關(guān)系。

角色

  • Target(目標(biāo)抽象類(lèi)):目標(biāo)抽象類(lèi)定義客戶所需的接口,可以是一個(gè)抽象類(lèi)或接口,也可以是具體類(lèi)。
  • Adapter(適配器類(lèi)):它可以調(diào)用另一個(gè)接口,作為一個(gè)轉(zhuǎn)換器,對(duì)Adaptee和Target進(jìn)行適配。它是適配器模式的核心。
  • Adaptee(適配者類(lèi)):適配者即被適配的角色,它定義了一個(gè)已經(jīng)存在的接口,這個(gè)接口需要適配,適配者類(lèi)包好了客戶希望的業(yè)務(wù)方法。

優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

  • 將目標(biāo)類(lèi)和適配者類(lèi)解耦,通過(guò)引入一個(gè)適配器類(lèi)來(lái)重用現(xiàn)有的適配者類(lèi),無(wú)需修改原有結(jié)構(gòu)。
  • 增加了類(lèi)的透明性和復(fù)用性,將具體的業(yè)務(wù)實(shí)現(xiàn)過(guò)程封裝在適配者類(lèi)中,對(duì)于客戶端類(lèi)而言是透明的,而且提高了適配者的復(fù)用性,同一適配者類(lèi)可以在多個(gè)不同的系統(tǒng)中復(fù)用。
  • 靈活性和擴(kuò)展性都非常好,通過(guò)使用配置文件,可以很方便的更換適配器,也可以在不修改原有代碼的基礎(chǔ)上增加新的適配器,完全復(fù)合開(kāi)閉原則。

缺點(diǎn)

  • 過(guò)多地使用適配器,會(huì)讓系統(tǒng)非常零亂,不易整體進(jìn)行把握。
  • 由于 JAVA 至多繼承一個(gè)類(lèi),所以至多只能適配一個(gè)適配者類(lèi),而且目標(biāo)類(lèi)必須是抽象類(lèi),有一定的局限性。

使用場(chǎng)景

  • 系統(tǒng)需要使用一些現(xiàn)有的類(lèi),而這些類(lèi)的接口不符合系統(tǒng)的需要,甚至沒(méi)有這些類(lèi)的源代碼。
  • 創(chuàng)建一個(gè)可以重復(fù)使用的類(lèi),用于和一些彼此之間沒(méi)有太大關(guān)聯(lián)的類(lèi),包括一些可能在將來(lái)引進(jìn)的類(lèi)一起工作。

類(lèi)適配器和對(duì)象適配器的權(quán)衡

  • 類(lèi)適配器使用對(duì)象繼承的方式,是靜態(tài)的定義方式;而對(duì)象適配器使用對(duì)象組合的方式,是動(dòng)態(tài)組合的方式。
  • 對(duì)于類(lèi)適配器,由于適配器直接繼承了Adaptee,使得適配器不能和Adaptee的子類(lèi)一起工作,因?yàn)槔^承是靜態(tài)的關(guān)系,當(dāng)適配器繼承了Adaptee后,就不可能再去處理 Adaptee的子類(lèi)了。而對(duì)于對(duì)象適配器,一個(gè)適配器可以把多種不同的源適配到同一個(gè)目標(biāo)。換言之,同一個(gè)適配器可以把源類(lèi)和它的子類(lèi)都適配到目標(biāo)接口。因?yàn)閷?duì)象適配器采用的是對(duì)象組合的關(guān)系,只要對(duì)象類(lèi)型正確,是不是子類(lèi)都無(wú)所謂。
  • 對(duì)于類(lèi)適配器,適配器可以重定義Adaptee的部分行為,相當(dāng)于子類(lèi)覆蓋父類(lèi)的部分實(shí)現(xiàn)方法。而對(duì)于對(duì)象適配器,要重定義Adaptee的行為比較困難,這種情況下,需要定義Adaptee的子類(lèi)來(lái)實(shí)現(xiàn)重定義,然后讓適配器組合子類(lèi)。雖然重定義Adaptee的行為比較困難,但是想要增加一些新的行為則方便的很,而且新增加的行為可同時(shí)適用于所有的源。
  • 對(duì)于類(lèi)適配器,僅僅引入了一個(gè)對(duì)象,并不需要額外的引用來(lái)間接得到Adaptee。而對(duì)于對(duì)象適配器,需要額外的引用來(lái)間接得到Adaptee。

????建議盡量使用對(duì)象適配器的實(shí)現(xiàn)方式,多用合成/聚合、少用繼承。當(dāng)然,具體問(wèn)題具體分析,根據(jù)需要來(lái)選用實(shí)現(xiàn)方式,最適合的才是最好的。

示例

類(lèi)適配器

/**
 * 需要適配的類(lèi)
 */
public class Adaptee {

    public void specificRequest(){
        System.out.println("系統(tǒng)原有的接口");
    }
}
/**
 * 客戶端需要的接口
 */
public interface Target {
    /**
     * 客戶端需要的接口
     */
    void request();
}
/**
 * 適配器,最終客戶需要的類(lèi)
 */
public class Adapter extends Adaptee implements Target{

    /**
     * 客戶端需要的接口
     */
    @Override
    public void request() {
        System.out.println("客戶端需要的接口");
    }
}

對(duì)象適配器

/**
 * 需要適配的類(lèi)
 */
public class Adaptee {

    public void specificRequest(){
        System.out.println("系統(tǒng)原有的接口");
    }
}
/**
 * 客戶端需要的接口
 */
public interface Target {
    /**
     * 客戶端需要的接口
     */
    void request();
}
/**
 * 適配器,最終客戶需要的類(lèi)
 */
public class Adapter implements Target {
    private Adaptee adaptee;

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

    /**
     * 客戶端需要的接口
     */
    @Override
    public void request() {
        System.out.println("客戶端需要的接口");
    }

    /**
     * 系統(tǒng)原有的接口
     */
    public void specificRequest() {
        this.adaptee.specificRequest();
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容