前言
買過(guò)港版手機(jī)的都知道,包裝盒里送的充電頭是港標(biāo)的。和我們大陸日常使用的國(guó)標(biāo)是不兼容的。也就是說(shuō),港版手機(jī)直接用送的充電頭是無(wú)法在大陸直接充電的。這是由于大陸使用國(guó)標(biāo)插座,而HK是使用的英標(biāo)插座。如下圖所示,可以看到國(guó)標(biāo),港版英標(biāo)的是不同接口的插座。

而為了解決這個(gè)不兼容的問(wèn)題,通常使用電源接頭轉(zhuǎn)換器,這種轉(zhuǎn)換器一頭是英標(biāo)接口,另一頭是國(guó)標(biāo)插頭。有了轉(zhuǎn)換器,我們可以在不更換插座接口,也不更換充電器的前提下,成功將我們的港版手機(jī)充電。

在軟件開發(fā)中,我們也會(huì)遇到需要“電源接頭轉(zhuǎn)換器”的時(shí)候。比如說(shuō),需要使用現(xiàn)有的類,但是類的接口并不符合我們的需要,甚至是并沒有這些類的源代碼。此時(shí),適配器模式就是我們的轉(zhuǎn)化器。
是什么
適配器模式(Adapter Pattern):將一個(gè)接口轉(zhuǎn)換成客戶希望的另一個(gè)接口,使接口不兼容的那些類可以一起工作,其別名為包裝器(Wrapper)。適配器模式既可以作為類結(jié)構(gòu)型模式,也可以作為對(duì)象結(jié)構(gòu)型模式。常用作在不修改源代碼的情況下讓已經(jīng)存在的類能和其他類一起使用。
根據(jù)適配器類和適配者類的關(guān)系,適配器模式可以分為以下兩種:
對(duì)象適配器模式(組合的方式)
-
類適配器模式(繼承的方式)
兩種適配器模式(左邊對(duì)象適配器模式,右邊類適配器模式) Target:目標(biāo)抽象類,定義客戶所需的接口,可以是抽象類/接口/具體類。
Adaptee:適配者類,也就是被適配的對(duì)象。定義一個(gè)已經(jīng)存在的接口。一般是一個(gè)具體類,其中包含了客戶希望使用的業(yè)務(wù)方法。
Adapter:適配器類,轉(zhuǎn)換器,對(duì)目標(biāo)類和適配者類進(jìn)行適配。
為什么
試想一下,如果我們不使用適配器模式,我們可以選擇修改源碼或者更改我們的目標(biāo)接口。而修改源碼或是更改接口很大的代價(jià)很大,甚至是我們根本就沒有源碼。就好像我們無(wú)法更換插座接口或是充電器的接頭一樣。
怎么做
由于適配器模式有多種,下面通過(guò)幾個(gè)代碼片段來(lái)分別學(xué)習(xí)一下:
- 對(duì)象適配器模式
首先是我們要使用的目標(biāo)接口,這個(gè)就好比是國(guó)標(biāo)插座。
/**
* 目標(biāo)接口
*/
public interface Target {
void request();
}
然后是我們的適配者類,同樣這個(gè)好比是港版英標(biāo)插頭。
/**
* 適配者類
*/
public class Adaptee {
/**
* 客戶期望使用的業(yè)務(wù)方法
*/
public void specificRequest(){
System.out.println("Adaptee Specific request!");
}
}
下面是適配器類,使用的是對(duì)象適配器模式,適配器類以組合的方式引用適配者類。這個(gè)就相當(dāng)于電源接頭轉(zhuǎn)換器。
/**
* 適配器類(對(duì)象適配器模式實(shí)現(xiàn))
*/
public class Adapter implements Target {
//以組合的方式關(guān)聯(lián)適配者
private Adaptee adaptee;
public Adapter(Adaptee adaptee){
this.adaptee = adaptee;
}
public void setAdaptee(Adaptee adaptee) {
this.adaptee = adaptee;
}
/**
* 對(duì)接口進(jìn)行轉(zhuǎn)換
*/
@Override
public void request() {
adaptee.specificRequest();
}
}
- 類適配器模式
而類適配器模式則是通過(guò)繼承的方式,而Java語(yǔ)言只支持單繼承,所以用得不多。
/**
* 類適配器模式
*/
public class Adapter extends Adaptee implements Target {
@Override
public void request() {
specificRequest();
}
}
實(shí)際使用:
public class Client {
public static void main(String[]args){
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
target.request();
}
}
