1 概述
適配器模式(Adapter),說白了就是為了掛羊頭賣狗肉而專門設計的模式。也就是把一個類的接口變換成客戶端所期待的另一種接口。
適配器模式通過定義一個新的接口(對要實現的功能加以抽象),和一個實現該接口的Adapter(適配器)類來透明地調用外部組件。這樣替換外部組件時,最多只要修改幾個Adapter類就可以了,其他源代碼都不會受到影響。
還是以手機為例子,每一種機型都自帶有從電器,有一天自帶充電器壞了,而且市場沒有這類型充電器可買了,怎么辦?萬能充電器就可以解決,這個萬能充電器就是適配器。
適配器模式有兩種形式,一種是類的適配,另一種自然就是對象的適配。
1.1 類的適配
這種適配方式,由以下幾個角色組成:
(1)目標(Target)角色:這就是所期待得到的接口。注意:由於這里討論的是類適配器模式,因此目標不可以是類。
(2)源(Adapee)角色:現在需要適配的接口。
(3)適配器(Adaper)角色:適配器類是本模式的核心。適配器把源接口轉換成目標接口。顯然,這一角色不可以是接口,而必須是具體類。
1.2 對象的適配
對象的適配依賴於對象的組合,而不是類適配中的繼承。
直接上例子來說明更容易理解。
2 示例
首先來一個IPhone的充電器類(Adaptee角色):
1 package org.scott.adapter; 2 /** 3 * @author Scott 4 * @date 2013-11-23 5 * @description 6 */ 7 public class IPhoneCharger { 8 public void applePhoneCharge(){ 9 System.out.println("The iPhone is charging ..."); 10 } 11 }
現在,要對這個特殊的充電器進行適配,上個適配的接口(Target角色):
1 package org.scott.adapter; 2 /** 3 * @author Scott 4 * @date 2013-11-23 5 * @description 6 */ 7 public interface ChargeAdapter { 8 public void phoneCharge(); 9 }
因為適配有兩種,所以先進行類的適配示例,創建類的適配器:
1 package org.scott.adapterclass; 2 3 import org.scott.adapter.ChargeAdapter; 4 import org.scott.adapter.IPhoneCharger; 5 6 /** 7 * @author Scott 8 * @date 2013-11-23 9 * @description 10 */ 11 public class UniversalCharger extends IPhoneCharger implements ChargeAdapter{ 12 13 @Override 14 public void phoneCharge() { 15 System.out.println("The phone is charging, but which kind of phone it is, who cares ..."); 16 17 //iphone charging 18 super.applePhoneCharge(); 19 } 20 21 }
這就是萬能充電器了,我們讓它來充個電,測試類准備:
1 package org.scott.adapterclass; 2 3 import org.scott.adapter.ChargeAdapter; 4 5 /** 6 * @author Scott 7 * @date 2013-11-23 8 * @description 9 */ 10 public class AdapterClassTest { 11 12 public static void main(String[] args) { 13 ChargeAdapter charger = new UniversalCharger(); 14 charger.phoneCharge(); 15 } 16 17 }
充電結果:
The phone is charging, but which kind of phone it is, who cares ...
The iPhone is charging ...
ok,以上是類的適配,我們還有種對象的適配方式,創建對象的適配器:
1 package org.scott.adapterobject; 2 3 import org.scott.adapter.ChargeAdapter; 4 import org.scott.adapter.IPhoneCharger; 5 6 /** 7 * @author Scott 8 * @date 2013-11-23 9 * @description 10 */ 11 public class UniversalCharger implements ChargeAdapter{ 12 IPhoneCharger iphoneCharger; 13 14 public UniversalCharger(IPhoneCharger iphoneCharger){ 15 this.iphoneCharger = iphoneCharger; 16 } 17 18 @Override 19 public void phoneCharge() { 20 System.out.println("The phone is charging, but which kind of phone it is, who cares ..."); 21 iphoneCharger.applePhoneCharge(); 22 } 23 24 25 }
新一代對象適配器創建完畢,測一把:
1 package org.scott.adapterobject; 2 3 import org.scott.adapter.ChargeAdapter; 4 import org.scott.adapter.IPhoneCharger; 5 6 /** 7 * @author Scott 8 * @date 2013-11-23 9 * @description 10 */ 11 public class AdapterObjectTest { 12 13 public static void main(String[] args) { 14 IPhoneCharger iphoneCharger = new IPhoneCharger(); 15 ChargeAdapter charger = new UniversalCharger(iphoneCharger); 16 charger.phoneCharge(); 17 } 18 19 }
運行結果:
The phone is charging, but which kind of phone it is, who cares ...
The iPhone is charging ...
ok,目的也達到了。
小節一下。
(1)類的適配器模式:當希望將一個類轉換成滿足另一個新接口的類時,可以使用類的適配器模式,創建一個新類,繼承原有的類,實現新的接口即可。
(2)對象的適配器模式:當希望將一個對象轉換成滿足另一個新接口的對象時,可以創建一個包裝類,持有原類的一個實例,在包裝類的方法中,調用實例的方法就行。
自然,最后還是要來個UML圖(源自網絡):
類適配:
對象適配: