1. 定義:
適配器模式的定義是,Convert the interface of a class into another interface clients expect,將某個類的接口轉換爲接口客戶所需的類型。適配器模式解決的問題是,使得原本由於接口不兼容而不能一起工作、不能統一管理的那些類可以在一起工作、可以進行統一管理。將一個接口轉換成客戶希望的另一個接口,適配器模式使接口不兼容的那些類可以一起工作,其別名爲包裝器。
個人覺得這些定義不太容易理解,但是我找到一句話,覺得更符合我對適配器模式的理解:適配器是爲了不改變有的代碼實現,但是又要滿足現有的需求,更像是屬於一種被動選擇。
Adapter模式的宗旨:保留現有類所提供的服務,向客戶提供接口,以滿足客戶的期望
2.先舉一個例子,現在有一個方法,而這個方法可以產生220V的電壓,然後我買了一個手機,手機充電電壓是5V,如何用220V的方法給5V的手機充電,同時有又不改變原有的220V電壓的方法。那麼我就需要一個手機充電器來作爲適配,將220V電壓,轉化爲5V的電壓,手機充電器就是適配器類。(注意,不要對我舉例產生固有思維,舉例只是爲了形象理解,事實上適配器就是爲了:保留現有類所提供的服務,向客戶提供接口,以滿足客戶的期望)
2.1 適配器有類 適配器 和 對象適配器
以上面的例子來實現類適配器代碼,先有一個供電站接口,各個地區供電站都可以實現這個接口,提供不同的電壓
/**
* 供電站 接口
* @author lx
*
*/
public interface PowerStation {
/**
* 供電接口 返回電壓
* @return
*/
public int providePower();
}
2.2.現有亳州供電站爲用戶提供220V電壓供電,具體實現
public class BoZhouPowerStation implements PowerStation{
@Override
public int providePower() {
// 我這裏舉例比代碼較少,一般項目中可能有複雜的業務邏輯
return 220;
}
}
2.3.現在我手機沒電了,想要給手機充電,我就多寫一個手機充電接口
/**
* 手機充電接口
* @author lx
*
*/
public interface PhoneCharge {
public String chargePower();
}
2.4.我要給我的華爲手機充電,華爲手機實現手機充電接口,具有充電的能力,但是需要5V電壓進行充電,但是我們只有220V電壓的實現類,當電壓實現類是比較複雜的,就像亳州供電站一樣,不可能爲了手機充電,提供一個5V電壓供電站。(如果在代碼中,類似於電壓實現類比較簡單,也可以實現供電站接口,提供一個5V的電壓 ,直接調用即可)
public class HuaWeiPhone implements PhoneCharge{
//需要5V電壓進行充電
@Override
public String chargePower() {
return null;
}
}
現在需要對上述代碼進行改造,保持原有220V電壓實現類不變,因爲可能有其它地方調用,改造後的代碼
public class HuaWeiPhone extends BoZhouPowerStation implements PhoneCharge{
@Override
public String chargePower() {
//獲取220v電壓操作
int voltage = this.providePower();
//將電壓轉化爲5v操作
int phoneVoltage = voltage/44;
System.out.println("通過亳州供電站爲華爲手機充電,電壓:"+phoneVoltage+"V");
return phoneVoltage+"V";
}
}
我們new 一個華爲手機對象,執行上述方法,即可爲華爲手機充電。上述通過繼承實現兩個接口的連接,即爲類適配器模式,這種模式的缺點會增加代碼的耦合性,不太靈活。
3.對象適配器模式 代碼 現在我使用小米手機,充電需要10V電壓
public class XiaoMiPhone implements PhoneCharge{
public BoZhouPowerStation bzs;
public XiaoMiPhone() {
bzs = new BoZhouPowerStation();
}
@Override
public String chargePower() {
//獲取220v電壓操作
int voltage = bzs.providePower();
//將電壓轉化爲10v操作
int phoneVoltage = voltage/22;
System.out.println("同過亳州供電站獲取手機充電電壓:"+phoneVoltage+"V");
return phoneVoltage+"V";
}
4. 上述實現方式不太好的地方在與,我的小米手機只能使用亳州供電站,並且這個亳州供電站還是小米充電器自帶的。還是不夠靈活,修改爲如下:
public class XiaoMiPhone implements PhoneCharge{
public BoZhouPowerStation bzs;
public XiaoMiPhone(BoZhouPowerStation bzs) {
this.bzs = bzs;
}
@Override
public String chargePower() {
//獲取220v電壓操作
int voltage = bzs.providePower();
//將電壓轉化爲10v操作
int phoneVoltage = voltage/22;
System.out.println("同過亳州供電站獲取手機充電電壓:"+phoneVoltage+"V");
return phoneVoltage+"V";
}
}
5.上述代碼,也不夠靈活,雖然亳州供電站不用在代碼內部創建了,但是我出差到上海想使用上供電站的電對我的手機進行充電,需要做如下修改:
public class XiaoMiPhone implements PhoneCharge{
public PowerStation ps;
public XiaoMiPhone(PowerStation ps) {
this.ps = ps;
}
@Override
public String chargePower() {
//獲取220v電壓操作
int voltage = ps.providePower();
//將電壓轉化爲10v操作
int phoneVoltage = voltage/22;
System.out.println("同過亳州供電站獲取手機充電電壓:"+phoneVoltage+"V");
return phoneVoltage+"V";
}
}
6.適配器模式的使用場景
(1)其中一個使用的場景是像上面所說的一樣,有兩個接口,你主動的想去連接着兩個接口,寫個適配器,感覺這種情況也不是很多,因爲很多時候都是些一個實體類對象調用另一個實體類對象。
(2)被動使用的情況比較多。舉個栗子,你開發新版本的時候重新定義了接口,要和舊版本寫適配的時候,爲了方便也可以使用適配器模式。