適配器模式是把一個類的接口變成客戶端所期待的另外一種接口,從而使本來因接口不匹配而沒法在一塊兒工做的兩個類可以在一塊兒工做。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(){ //寫相關的代碼 } }
類適配器與對象適配器的權衡
綜上,儘可能以對象適配器的實現方式爲主,多用聚合,少用繼承。固然具體問題具體分析,根據實際須要選擇(我的認爲實際上就不必對源類進行重寫,若是須要進行重寫直接對源類進行修改就好了,除非是沒有代碼權限,不過若是沒有權限的話,那麼源類對你來說更不可見,也就更沒有重寫的必要了吧。)。
更好的複用性:
系統須要使用現有的類,而此類的接口不符合系統的須要,那麼經過適配器模式可讓類得到更好的複用。
更好的擴展性:
在適配器實現功能的時候,也能夠調用本身的功能,從而擴展系統的功能。
過多的適配器,會讓系統顯得更加凌亂,不容易把控。
重構的代價合適的話,確實要比適配器更合適。