一天一個設計模式:適配器模式

概念:

  適配器模式是把一個類的接口變成客戶端所期待的另外一種接口,從而使本來因接口不匹配而沒法在一塊兒工做的兩個類可以在一塊兒工做。api

用途:

  就像插頭轉換器,以前入了switch港版,插頭是英式的,還好附贈一個插頭轉換器,適配器就至關於這個轉換器。ide

種類:

  分爲類的適配器與對象的適配器兩種this

 

類適配器:

  把適配的類的api轉化爲目標類的apispa

上圖中Adaptee沒有2方法,可是客戶端卻指望調用2方法。爲了客戶端可以使用Adaptee類,提供中間類Adapter,把Adaptee與Target的api組合起來,Adapter與Adaptee是繼承關係,因此這決定了適配器是類適配器。code

涉及到的角色:對象

  目標(Target)角色:這就是所期待獲得的接口。注意:因爲這裏討論的是類適配器,所以目標不能是類。blog

  源(Adapee)角色:如今須要適配的接口。繼承

  適配器(Adapter)角色:適配器類是本模式的核心。適配器把源接口轉化成目標接口,顯然這一角色不能夠是接口必須是具體類。接口

類適配器代碼:get

public interface Target {
    /**
     * 這是源類Adaptee也有的方法
     */
    public void sampleOperation1(); 
    /**
     * 這是源類Adapteee沒有的方法
     */
    public void sampleOperation2(); 
}
public class Adaptee {
    
    public void sampleOperation1(){}

}
public class Adapter extends Adaptee implements Target {
    /**
     * 因爲源類Adaptee沒有方法sampleOperation2()
     * 所以適配器補充上這個方法
     */
    @Override
    public void sampleOperation2() {
        //寫相關的代碼
    }

}

適配器Adapter擴展了源類,也實現了目標接口,且提供了源類沒有的接口的實現。


 

對象適配器模式

  對象適配器與類適配器不一樣的地方在於,對象適配器採用委派的方式將源類與適配器關聯到一塊兒(類適配器採用繼承)

 

 

源代碼:

 

public interface Target {
    /**
     * 這是源類Adaptee也有的方法
     */
    public void sampleOperation1(); 
    /**
     * 這是源類Adapteee沒有的方法
     */
    public void sampleOperation2(); 
}

 

public class Adaptee {

    public void sampleOperation1(){}
    
}
public class Adapter {
    private Adaptee adaptee;
    
    public Adapter(Adaptee adaptee){
        this.adaptee = adaptee;
    }
    /**
     * 源類Adaptee有方法sampleOperation1
     * 所以適配器類直接委派便可
     */
    public void sampleOperation1(){
        this.adaptee.sampleOperation1();
    }
    /**
     * 源類Adaptee沒有方法sampleOperation2
     * 所以由適配器類須要補充此方法
     */
    public void sampleOperation2(){
        //寫相關的代碼
    }
}

類適配器與對象適配器的權衡

 

  • 類適配器使用對象繼承的方式,是靜態的定義方式;而對象適配器使用的是對象組合的方式,是動態組合的方式。
  • 對於類適配器,因爲適配器直接繼承了Adaptee,使得適配器不能和Adaptee的子類一塊兒工做,由於繼承是靜態的,當適配器繼承Adaptee後,就不能再處理,Adaptee的子類。
  • 對於對象適配器,一個適配器能夠把不一樣的源類適配到同一個目標中,換一種說法,同一個適配器能夠把源類和它的子類都適配到目標接口。由於對象適配器採用的是對象組合的關係,只要類型正確,是否是子類都無所謂。
  • 對於類適配器,適配器能夠重定義部分Adaptee的部分行爲,至關於子類覆蓋父類的方法。
  • 對於對象適配器,要從新定義源類的的行爲很困難,這種狀況下,須要定義Adaptee的子類來實現重定義,而後讓適配器從新適配,雖然重定義Adaptee比較困難,可是想要增長一些新的行爲則很方便,並且新增的行爲能夠適配全部的源。
  • 對於類適配器,僅僅引入了一個對象,並不須要額外的引用來間接獲得Adaptee。
  • 對於對象適配器,須要額外的引用來簡介獲得Adaptee。

綜上,儘可能以對象適配器的實現方式爲主,多用聚合,少用繼承。固然具體問題具體分析,根據實際須要選擇(我的認爲實際上就不必對源類進行重寫,若是須要進行重寫直接對源類進行修改就好了,除非是沒有代碼權限,不過若是沒有權限的話,那麼源類對你來說更不可見,也就更沒有重寫的必要了吧。)。

適配器的優勢:

  更好的複用性:

    系統須要使用現有的類,而此類的接口不符合系統的須要,那麼經過適配器模式可讓類得到更好的複用。

  更好的擴展性:

    在適配器實現功能的時候,也能夠調用本身的功能,從而擴展系統的功能。

適配器的缺點:

  過多的適配器,會讓系統顯得更加凌亂,不容易把控。

  重構的代價合適的話,確實要比適配器更合適。

相關文章
相關標籤/搜索