五分鐘了解設(shè)計(jì)模式(3)---適配器模式

生活中的一些例子

在我們的日常生活中,對(duì)于適配器,可以說是無處不在。例如我們平時(shí)使用的筆記本電腦,可能筆記本電腦的工作電壓是20V,但我們一般的家庭用電是220V,這時(shí)候電腦在充電的時(shí)候就需要一個(gè)電源適配器來把220V的電腦轉(zhuǎn)化為20V的電壓了。這個(gè)電源適配器也別稱為充電器或變壓器。

image

又如,我們想用蘋果的充電線給安卓的手機(jī)充電時(shí)。由于兩者的接口不一樣,會(huì)導(dǎo)致充電口無法匹配。這時(shí),我們就需要適配器,將安卓的充電接口轉(zhuǎn)化為蘋果的接口,這樣,就可以進(jìn)行充電了。


image

上面說的兩個(gè)例子,就是今天我們要講的適配器模式。

適配器模定義

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

在適配器模式中,存在兩種不同的模式結(jié)構(gòu):類的適配器模式和對(duì)象的適配器模式

對(duì)象的適配器模式

我們以上面的蘋果充電線給安卓手機(jī)充電的為例,如果是你來寫代碼,把他們進(jìn)行兼容適配,你會(huì)怎么寫呢?

對(duì)于這個(gè)問題,我們首先先來看一下適配器模式中涉及到的三個(gè)角色:

1、Target(目標(biāo)抽象類):目標(biāo)抽象類定義客戶所需接口,可以是一個(gè)抽象類或接口,也可以是具體類。例如對(duì)于上面的第二個(gè)例子,客戶端的目標(biāo)是要給只接受安卓充電口的安卓手機(jī)充電,所以我們的目標(biāo)抽象類就是安卓充電線的接口

2、Adaptee(適配者類):適配者即被適配的角色,它定義了一個(gè)已經(jīng)存在的接口,這個(gè)接口需要適配,適配者類一般是一個(gè)具體類,包含了客戶希望使用的業(yè)務(wù)方法。例如上面蘋果充電線就是適配者類。

3、Adapter(適配器類):通過包裝一個(gè)需要適配的對(duì)象,把原接口轉(zhuǎn)換成目標(biāo)接口。例如為了可以充電,我們需要一個(gè)適配器,使之一邊可以連接安卓充電的接口,一邊可以連接蘋果充電線的接口。

UML圖

image

下面我們用代碼來做個(gè)實(shí)例:

(1).Target類

public class Android {
    public void isAndroid(){
        System.out.println("這是一個(gè)只接受安卓充電線的插口");
    }
}

(2).Adaptee類

public class Iphone {
    public void isIphone(){
        System.out.println("這是一個(gè)適配蘋果充電線的插口");
    }
}

(3).Adapter類:把他們進(jìn)行適配

/**
 * 適配器,作為中間件,把他們進(jìn)行適配
 */
public class Adapter extends Android{
    private Iphone iphone;

    public Adapter(Iphone iphone){
        this.iphone = iphone;
    }

    @Override
    public void isAndroid() {
        iphone.isIphone();
    }
}

(4).測(cè)試類

public class Demo {
    public static void main(String[] args){
        Android android = new Adapter(new Iphone());
        //調(diào)用的是安卓的接口,但實(shí)際上
        //確實(shí)一個(gè)可以接受蘋果充電器的接口
        android.isAndroid();
    }
}

(5).打印結(jié)果

這是一個(gè)適配蘋果充電線的插口

我們通過適配器的作用,就可以讓蘋果充電線給安卓手機(jī)充電了。。

對(duì)于這種對(duì)象的適配器模式,實(shí)際上就是通過一個(gè)適配器類,把目標(biāo)類和需要被適配的類進(jìn)行組合。所以適配器類Adapter一般需要繼承或?qū)崿F(xiàn)Targert,并且還得持有Adaptee的實(shí)例引用。

類的適配器模式

除了對(duì)象的適配器模式,還有另外一種類的適配器模式。在這種模式中,Adapter不持有Adaptee的實(shí)例引用,而是直接繼承Adaptee類,然后再實(shí)現(xiàn)Target接口?;蛘咧苯永^承Adaptee類和Target類,但由于Java中不支持多重繼承,所以只能用實(shí)現(xiàn)Target的方式。

這也導(dǎo)致了在Jaca類的適配器模式中,Target必須是一個(gè)接口而不可以是抽象類和具體類(因?yàn)镴ava不支持多重繼承)。

把上面那個(gè)例子改寫一下,用類的適配器模式來實(shí)現(xiàn):

(1).Target接口類

interface Android {
    void isAndroid();
}

(2).Adaptee類

public class Iphone {
    public void isIphone(){
        System.out.println("這是一個(gè)適配蘋果充電線的接口");
    }
}

(3).Adapter類:繼承Adaptee,實(shí)現(xiàn)Target

/**
 * 適配器,把安卓手機(jī)的插口轉(zhuǎn)化為可以用蘋果充電線充電的接口
 */
public class Adapter extends Iphone implements Android{
    @Override
    public void isAndroid() {
        //直接調(diào)用
        isIphone();
    }
}

(4).測(cè)試類

public class Demo {
    public static void main(String[] args){
        Android android = new Adapter();
        android.isAndroid();
    }
}

(5).打印結(jié)果

這是一個(gè)適配蘋果充電線的接口

對(duì)于這種類的適配器模式,在Java中是使用的比較少的。

這兩種方式最重要的區(qū)別就是:

對(duì)象適配器模式通過組合來實(shí)現(xiàn)適配器功能,而類的適配器模式通過多繼承或?qū)崿F(xiàn)來實(shí)現(xiàn)適配器功能。

適配器模式的一些優(yōu)缺點(diǎn)

感覺,優(yōu)缺點(diǎn)沒什么好說的,只有實(shí)際上去用過才能體會(huì)。反正最重要的優(yōu)點(diǎn)就是將不兼容的幾個(gè)接口通過一個(gè)中間類,把他們進(jìn)行適配,并且這個(gè)適配的過程對(duì)于客戶端來說是透明的,客戶端并不知道發(fā)生了啥,只知道它通過一個(gè)適配器,就可以獲取到目標(biāo)接口了。

至于缺點(diǎn)嘛,如果動(dòng)不動(dòng)就使用適配器,那么我覺得會(huì)使整個(gè)類系統(tǒng)變的有點(diǎn)零散,并且以后要重構(gòu)了會(huì)更加復(fù)雜......

關(guān)注公我的眾號(hào):苦逼的碼農(nóng),獲取更多原創(chuàng)文章,后臺(tái)回復(fù)禮包送你一份時(shí)下熱門的資源大禮包。同時(shí)也感謝把文章介紹給更多需要的人

?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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