06 適配器模式(Adapter Design Pattern)

一句話概括:有點(diǎn)數(shù)據(jù)類型轉(zhuǎn)化輔助類的意思。

適配器模式將某個(gè)類的接口轉(zhuǎn)換成客戶端期望的另一個(gè)接口表示,主的目的是兼容性,讓原本因接口不匹配不能一起工作的兩個(gè)類可以協(xié)同工作。其別名為包裝器(Wrapper)。

需要被適配的類、接口、對象(我們有的),簡稱 src(source)

最終需要的輸出(我們想要的),簡稱 dst (destination,即Target)

適配器稱之為 Adapter 。

一句話描述適配器模式的感覺: src->Adapter->dst, 即src以某種形式(三種形式分別對應(yīng)三種適配器模式)給到Adapter里,最終轉(zhuǎn)化成了dst。

適配器設(shè)計(jì)模式的一個(gè)非常實(shí)際的例子是電源適配器。 手機(jī)電池充電電壓是3伏,但正常插座可以產(chǎn)生120V(美國)、240V(印度)、220V(中國)等。 因此,電源適配器可作為移動充電器和墻上插座之間的適配器。

接下來我們嘗試使用適配器模式實(shí)現(xiàn)多適配器。

//電壓
public class Volt {

    private int volts;

    public Volt(int v){
        this.volts=v;
    }

    public int getVolts() {
        return volts;
    }

    public void setVolts(int volts) {
        this.volts = volts;
    }

}
//墻上的插座,輸出120V電壓
public class Socket {

    public Volt getVolt(){
        return new Volt(120);
    }
}

現(xiàn)在我們要構(gòu)建一個(gè)可產(chǎn)生3伏,12伏和默認(rèn)120伏的適配器。所以首先我們創(chuàng)建一個(gè)適配器接口。

public interface SocketAdapter {

    public Volt get120Volt();

    public Volt get12Volt();

    public Volt get3Volt();
}

Two Way Adapter Pattern

在實(shí)現(xiàn)適配器模式時(shí),有兩種方法 - 類適配器和對象適配器 - 但是這兩種方法都會產(chǎn)生相同的結(jié)果。

  • 類適配器(Class Adapter) - 這種形式使用JAVA繼承(java inheritance)并擴(kuò)展了原始接口,在我們的例子中是Socket類。
  • 對象適配器(Object Adapter) - 此種形式使用JAVA組合(Java Composition)并且適配器包含原始對象。

Adapter Design Pattern – Class Adapter

//Using inheritance for adapter pattern
public class SocketClassAdapterImpl extends Socket implements SocketAdapter{

    @Override
    public Volt get120Volt() {
        return getVolt();
    }

    @Override
    public Volt get12Volt() {
        Volt v= getVolt();
        return convertVolt(v,10);
    }

    @Override
    public Volt get3Volt() {
        Volt v= getVolt();
        return convertVolt(v,40);
    }

    private Volt convertVolt(Volt v, int i) {
        return new Volt(v.getVolts()/i);
    }

}

Adapter Design Pattern – Object Adapter Implementation

public class SocketObjectAdapterImpl implements SocketAdapter{

    //Using Composition for adapter pattern
    private Socket sock = new Socket();

    @Override
    public Volt get120Volt() {
        return sock.getVolt();
    }

    @Override
    public Volt get12Volt() {
        Volt v= sock.getVolt();
        return convertVolt(v,10);
    }

    @Override
    public Volt get3Volt() {
        Volt v= sock.getVolt();
        return convertVolt(v,40);
    }

    private Volt convertVolt(Volt v, int i) {
        return new Volt(v.getVolts()/i);
    }
}

注意兩種適配器的實(shí)現(xiàn)幾乎相同,他們都繼承了SocketAdapter接口。適配器接口也可以是個(gè)抽象類。

下面是測試代碼:

public class AdapterPatternTest {

    public static void main(String[] args) {

        testClassAdapter();
        testObjectAdapter();
    }

    private static void testObjectAdapter() {
        SocketAdapter sockAdapter = new SocketObjectAdapterImpl();
        Volt v3 = getVolt(sockAdapter,3);
        Volt v12 = getVolt(sockAdapter,12);
        Volt v120 = getVolt(sockAdapter,120);
        System.out.println("v3 volts using Object Adapter="+v3.getVolts());
        System.out.println("v12 volts using Object Adapter="+v12.getVolts());
        System.out.println("v120 volts using Object Adapter="+v120.getVolts());
    }

    private static void testClassAdapter() {
        SocketAdapter sockAdapter = new SocketClassAdapterImpl();
        Volt v3 = getVolt(sockAdapter,3);
        Volt v12 = getVolt(sockAdapter,12);
        Volt v120 = getVolt(sockAdapter,120);
        System.out.println("v3 volts using Class Adapter="+v3.getVolts());
        System.out.println("v12 volts using Class Adapter="+v12.getVolts());
        System.out.println("v120 volts using Class Adapter="+v120.getVolts());
    }

    private static Volt getVolt(SocketAdapter sockAdapter, int i) {
        switch (i){
        case 3: return sockAdapter.get3Volt();
        case 12: return sockAdapter.get12Volt();
        case 120: return sockAdapter.get120Volt();
        default: return sockAdapter.get120Volt();
        }
    }
}

測試代碼的輸出結(jié)果是:

v3 volts using Class Adapter=3
v12 volts using Class Adapter=12
v120 volts using Class Adapter=120
v3 volts using Object Adapter=3
v12 volts using Object Adapter=12
v120 volts using Object Adapter=120

Adapter Design Pattern Example in JDK

在JDK中可以很容易找出幾個(gè)簡單的適配器模式的應(yīng)用

java.util.Arrays#asList()
java.io.InputStreamReader(InputStream) (returns a Reader)
java.io.OutputStreamWriter(OutputStream) (returns a Writer)

使用場景

  • 系統(tǒng)需要使用現(xiàn)有的類,而這些類的接口不符合系統(tǒng)的需要。
  • 想要建立一個(gè)可以重復(fù)使用的類,用于與一些彼此之間沒有太大關(guān)聯(lián)的一些類,包括一些可能在將來引進(jìn)的類一起工作。
  • 需要一個(gè)統(tǒng)一的輸出接口,而輸入端的類型不可預(yù)知。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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