Java設計模式之適配器模式

目錄

一、概述

二、類適配器模式

三、對象適配器模式

四、接口適配器模式

五、適用場景


一、概述

將一個類的接口轉換成客戶希望的另外一個接口,適配器模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
適配器模式有兩種:類適配器、對象適配器、接口適配器。前二者在實現上有些許區別,作用一樣,第三個接口適配器差別較大。

優點:
1、將目標類和適配者類解耦;
2、增加了類的透明性和複用性,將具體的實現封裝在適配者類中,對於客戶端類來說是透明的,而且提高了適配者的複用性;
3、靈活性和擴展性都非常好,符合開閉原則;

角色:
目標(Target):定義一個客戶端使用的特定接口。
客戶端(Client):使用目標接口,與和目標接口一致的對象合作。
被適配者(Adaptee):一個現存需要適配的接口。
適配器(Adapter):負責將Adaptee的接口轉換爲Target的接口。適配器是一個具體的類,這是該模式的核心。

二、類適配器模式

所謂類適配器,指的是適配器Adapter繼承我們的被適配者Adaptee,並實現目標接口Target。由於Java中是單繼承,所以這個適配器僅僅只能服務於所繼承的被適配者Adaptee。

原理:通過繼承來實現適配器功能。

當我們要訪問的接口A中沒有我們想要的方法 ,卻在另一個接口B中發現了合適的方法,我們又不能改變訪問接口A,在這種情況下,我們可以定義一個適配器p來進行中轉,這個適配器p要實現我們訪問的接口A,這樣我們就能繼續訪問當前接口A中的方法(雖然它目前不是我們的菜),然後再繼承接口B的實現類BB,這樣我們可以在適配器P中訪問接口B的方法了,這時我們在適配器P中的接口A方法中直接引用BB中的合適方法,這樣就完成了一個簡單的類適配器。

假設現在有個type-c充電器接口頭子,但是手機是正常的usb接口頭子,這個時候需要一個轉化器將type-c接口換成usb接口,手機就可以充電了。

被適配者,typeC接口

public interface TypeC {
    public void isTypeC();
}

目標接口,usb接口

public interface Usb {
    public void isUsb();
}

假設我們的手機最終只能對接到usb接口,所以實現usb接口,而不實現typeC接口

public class UsbImpl implements Usb{
    @Override
    public void isUsb() {
        System.out.println("這是usb接口");
    }
}

適配器,將調用typeC的接口,適配到usb接口上。通過繼承UsbImpl來實現適配器功能。

public class Adapter extends UsbImpl implements TypeC {

    @Override
    public void isTypeC() {
        isUsb();
    }
}

測試類

public class ClientMain {
    public static void main(String[] args) {
        TypeC typeC = new Adapter();
         typeC.isTypeC();
    }
}

輸出
這是usb接口

三、對象適配器模式

所謂對象適配器,簡單的說就是適配器實現我們的目標接口,但是並不繼承需要被適配的類。而是通過在適配器的構造函數中將需要被適配的類傳遞進來從而進行適配。對象適配器可以適配多個帶適配的類。只需要你在Adapter的構造方法中傳遞不同的帶適配的類即可。具有靈活性。

原理:通過組合來實現適配器功能。

當我們要訪問的接口A中沒有我們想要的方法,卻在另一個接口B中發現了合適的方法,我們又不能改變訪問接口A,在這種情況下,我們可以定義一個適配器p來進行中轉,這個適配器p要實現我們訪問的接口A,這樣我們就能繼續訪問當前接口A中的方法(雖然它目前不是我們的菜),然後在適配器P中定義私有變量C(對象)(B接口指向變量名),再定義一個帶參數的構造器用來爲對象C賦值,再在A接口的方法實現中使用對象C調用其來源於B接口的方法。

代碼基本與上面一樣,只是在適配器不用繼承適配目標累了,而是直接實現接口,然後調用對象的方法。

public class Adapter implements Ps2 {
    
    private Usb usb;
    public Adapter(Usb usb){
        this.usb = usb;
    }
    @Override
    public void isTypec() {
        usb.isUsb();
    }

}

四、接口適配器模式

原理:通過抽象類來實現適配,這種適配稍別於上面所述的適配。

當存在這樣一個接口,其中定義了N多的方法,而我們現在卻只想使用其中的一個到幾個方法,如果我們直接實現接口,那麼我們要對所有的方法進行實現,哪怕我們僅僅是對不需要的方法進行置空(只寫一對大括號,不做具體方法實現)也會導致這個類變得臃腫,調用也不方便,這時我們可以使用一個抽象類作爲中間件,即適配器,用這個抽象類實現接口,而在抽象類中所有的方法都進行置空,那麼我們在創建抽象類的繼承類,而且重寫我們需要使用的那幾個方法即可。

目標接口:A

public interface A {
    void a();
    void b();
    void c();
    void d();
    void e();
    void f();
}

適配器:Adapter

public abstract class Adapter implements A {
    public void a(){}
    public void b(){}
    public void c(){}
    public void d(){}
    public void e(){}
    public void f(){}
}
public class Ashili extends Adapter {
    public void a(){
        System.out.println("實現A方法被調用");
    }
    public void d(){
        System.out.println("實現d方法被調用");
    }
}
public class Clienter {

    public static void main(String[] args) {
        A a = new Ashili();
        a.a();
        a.d();
    }

}

五、適用場景

類適配器與對象適配器的使用場景一致,僅僅是實現手段稍有區別,二者主要用於如下場景:

(1)想要使用一個已經存在的類,但是它卻不符合現有的接口規範,導致無法直接去訪問,這時創建一個適配器就能間接去訪問這個類中的方法。
(2)我們有一個類,想將其設計爲可重用的類(可被多處訪問),我們可以創建適配器來將這個類來適配其他沒有提供合適接口的類。
以上兩個場景其實就是從兩個角度來描述一類問題,那就是要訪問的方法不在合適的接口裏,一個從接口出發(被訪問),一個從訪問出發(主動訪問)。

接口適配器使用場景:

想要使用接口中的某個或某些方法,但是接口中有太多方法,我們要使用時必須實現接口並實現其中的所有方法,可以使用抽象類來實現接口,並不對方法進行實現(僅置空),然後我們再繼承這個抽象類來通過重寫想用的方法的方式來實現。這個抽象類就是適配器。
 

參考
https://www.jb51.net/article/100146.htm
https://www.cnblogs.com/V1haoge/p/6479118.html

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