Java23種設計模式之適配器模式(Adapter Pattern)

模式名稱:適配器模式;

定義:將一個類的接口變換成客戶端所期待的另外一種接口,從而使原本因接口不匹配而無法工作的兩個類能夠一起工作;

使用場景:有動機去修改一個已經投產中的接口,適配器模式可能是最適合的一種模式,符合系統擴展時候因需求而不符合系統的接口;一般詳細設計階段沒必要過多考慮適配器模式,主要是應用到後期的擴展當中;

與對象適配器的區別: 類適配器是類之間的繼承,對象適配器是對象的合成關係,也可以說是類的關聯關係,這是這兩者的根本區別!

Target目標角色:該角色定義把其他類轉換成目標接口;

Adapter源角色:就是你想轉換的那個對象,他是一個已經存在或者運行良好的類或者對象,經過適配器角色的包裝轉換成一個新的目標對象;

Adapter適配器角色:適配器模式的核心角色,其他兩個角色都是已經存在的,而適配器角色是需要新建立的,他的職責非常簡單就是把源角色轉換成目標角色,怎樣轉換?通過繼承或者類關聯的方式;

通用代碼:

5.代碼

我們想象一種實際生產環境中會遇到的一種場景:

曾經有一個正常使用的接口,隨着項目迭代,原本的實現已經不再滿足現在的需求,需要調用另外一個已有的方法來完成。

public interface Target {

    void targetMethod();
}
public class TargetImpl implements Target {
    public void targetMethod() {
        System.out.println("最初TargetImpl實現的targetMethod(),可是逐漸的不再適用");
    }
}

public class Adaptee {

    public void doSomething(){
        System.out.println("Adaptee:doSomething");
    }
}
上面是原本的接口,已經不再適用。爲了完成新的需求,需要使用Adaptee類中的doSomething()方法。那麼,如何在客戶端不更改代碼的情況下順利的用新的方法替換掉原本的實現呢?這個時候就需要用到適配器模式了。

5.1 類適配器模式

public class AdapterA extends Adaptee implements Target{
    public void targetMethod() {
        System.out.println("1.類適配器,採用繼承的方式實現");
        doSomething();
    }
}
新建一個類適配器AdapterA,繼承了需要適配的類Adaptee,同時實現目標接口Target。

測試方法:

public static void main(String[] args) {
    //最初的實現方法,在項目迭代過程中逐漸不再適用,需要新的邏輯來實現這個接口
    Target target = new TargetImpl();
    target.targetMethod();
    System.out.println("~~~~~~~~~~~~~~~~~~~~");

    //1.類適配器,採用繼承的方式實現
    Target adapterA = new AdapterA();
    adapterA.targetMethod();
}
測試結果:

最初TargetImpl實現的targetMethod(),可是逐漸的不再適用
~~~~~~~~~~~~~~~~~~~~
1.類適配器,採用繼承的方式實現
Adaptee:doSomething


5.2 對象適配器模式

public class AdapterB implements Target{

    private Adaptee adaptee = new Adaptee();

    public void targetMethod() {
        System.out.println("2.對象適配器,採用對象組合的方式實現");
        adaptee.doSomething();
    }
}
創建一個對象適配器AdapterB實現目標接口Target,通過對象組合的方式獲得一個適配的類Adaptee的引用,然後使用該引用中的方法。

測試方法:

public static void main(String[] args) {
    //最初的實現方法,在項目迭代過程中逐漸不再適用,需要新的邏輯來實現這個接口
    Target target = new TargetImpl();
    target.targetMethod();

    System.out.println("~~~~~~~~~~~~~~~~~~~~");

    //2.對象適配器,採用對象組合的方式實現
    Target adapterB = new AdapterB();
    adapterB.targetMethod();
}

測試結果:

最初TargetImpl實現的targetMethod(),可是逐漸的不再適用
~~~~~~~~~~~~~~~~~~~~
2.對象適配器,採用對象組合的方式實現
Adaptee:doSomething

以上2中適配器模式都成功地用已有的功能替換掉了原本不適用的功能,比較一下2中方式可以發現:

由於類適配器是通過繼承的方式使用父類的方法,總所周知java中一個類只能有一個父類,因此一個類適配器只能把適配者類和它的子類都適配到目標接口;而對象適配器可以通過持有不同的需要適配的類的引用,來實現擴展。這麼看來,對象適配器更靈活一點。


6.小結

6.1 優點

    6.1.1 通過適配器,客戶端可以調用同一接口,因而對客戶端來說是透明的。這樣做更簡單、更直接、更緊湊。

    6.1.2 複用了現存的類,解決了現存類和複用環境要求不一致的問題。

    6.1.3 將目標類和適配者類解耦,通過引入一個適配器類重用現有的適配者類,而無需修改原有代碼。

    6.1.4 一個對象適配器可以把多個不同的適配者類適配到同一個目標,也就是說,同一個適配器可以把適配者類和它的子類都適配到目標接口。

  6.2 缺點

    對於對象適配器來說,更換適配器的實現過程比較複雜。

  6.3 適用場景

    6.3.1 系統需要使用現有的類,而這些類的接口不符合系統的接口。

    6.3.2 想要建立一個可以重用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作。

    6.3.3 兩個類所做的事情相同或相似,但是具有不同接口的時候。

    6.3.4 舊的系統開發的類已經實現了一些功能,但是客戶端卻只能以另外接口的形式訪問,但我們不希望手動更改原有類的時候。

    6.3.5 使用第三方組件,組件接口定義和自己定義的不同,不希望修改自己的接口,但是要使用第三方組件接口的功能。


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