一句話概括:有點數(shù)據(jù)類型轉(zhuǎn)化輔助類的意思。
適配器模式將某個類的接口轉(zhuǎn)換成客戶端期望的另一個接口表示懂缕,主的目的是兼容性敷燎,讓原本因接口不匹配不能一起工作的兩個類可以協(xié)同工作。其別名為包裝器(Wrapper)拂共。
需要被適配的類、接口姻几、對象(我們有的)宜狐,簡稱 src(source)
最終需要的輸出(我們想要的),簡稱 dst (destination蛇捌,即Target)
適配器稱之為 Adapter 抚恒。
一句話描述適配器模式的感覺: src->Adapter->dst, 即src以某種形式(三種形式分別對應三種適配器模式)給到Adapter里,最終轉(zhuǎn)化成了dst络拌。
適配器設(shè)計模式的一個非常實際的例子是電源適配器俭驮。 手機電池充電電壓是3伏,但正常插座可以產(chǎn)生120V(美國)春贸、240V(印度)混萝、220V(中國)等。 因此萍恕,電源適配器可作為移動充電器和墻上插座之間的適配器逸嘀。
接下來我們嘗試使用適配器模式實現(xiàn)多適配器。
//電壓
public class Volt {
private int volts;
public Volt(int v){
this.volts=v;
}
public int getVolts() {
return volts;
}
public void setVolts(int volts) {
this.volts = volts;
}
}
//墻上的插座雄坪,輸出120V電壓
public class Socket {
public Volt getVolt(){
return new Volt(120);
}
}
現(xiàn)在我們要構(gòu)建一個可產(chǎn)生3伏厘熟,12伏和默認120伏的適配器屯蹦。所以首先我們創(chuàng)建一個適配器接口维哈。
public interface SocketAdapter {
public Volt get120Volt();
public Volt get12Volt();
public Volt get3Volt();
}
Two Way Adapter Pattern
在實現(xiàn)適配器模式時,有兩種方法 - 類適配器和對象適配器 - 但是這兩種方法都會產(chǎn)生相同的結(jié)果登澜。
- 類適配器(Class Adapter) - 這種形式使用JAVA繼承(java inheritance)并擴展了原始接口阔挠,在我們的例子中是Socket類。
- 對象適配器(Object Adapter) - 此種形式使用JAVA組合(Java Composition)并且適配器包含原始對象脑蠕。
Adapter Design Pattern – Class Adapter
//Using inheritance for adapter pattern
public class SocketClassAdapterImpl extends Socket implements SocketAdapter{
@Override
public Volt get120Volt() {
return getVolt();
}
@Override
public Volt get12Volt() {
Volt v= getVolt();
return convertVolt(v,10);
}
@Override
public Volt get3Volt() {
Volt v= getVolt();
return convertVolt(v,40);
}
private Volt convertVolt(Volt v, int i) {
return new Volt(v.getVolts()/i);
}
}
Adapter Design Pattern – Object Adapter Implementation
public class SocketObjectAdapterImpl implements SocketAdapter{
//Using Composition for adapter pattern
private Socket sock = new Socket();
@Override
public Volt get120Volt() {
return sock.getVolt();
}
@Override
public Volt get12Volt() {
Volt v= sock.getVolt();
return convertVolt(v,10);
}
@Override
public Volt get3Volt() {
Volt v= sock.getVolt();
return convertVolt(v,40);
}
private Volt convertVolt(Volt v, int i) {
return new Volt(v.getVolts()/i);
}
}
注意兩種適配器的實現(xiàn)幾乎相同购撼,他們都繼承了SocketAdapter接口跪削。適配器接口也可以是個抽象類。
下面是測試代碼:
public class AdapterPatternTest {
public static void main(String[] args) {
testClassAdapter();
testObjectAdapter();
}
private static void testObjectAdapter() {
SocketAdapter sockAdapter = new SocketObjectAdapterImpl();
Volt v3 = getVolt(sockAdapter,3);
Volt v12 = getVolt(sockAdapter,12);
Volt v120 = getVolt(sockAdapter,120);
System.out.println("v3 volts using Object Adapter="+v3.getVolts());
System.out.println("v12 volts using Object Adapter="+v12.getVolts());
System.out.println("v120 volts using Object Adapter="+v120.getVolts());
}
private static void testClassAdapter() {
SocketAdapter sockAdapter = new SocketClassAdapterImpl();
Volt v3 = getVolt(sockAdapter,3);
Volt v12 = getVolt(sockAdapter,12);
Volt v120 = getVolt(sockAdapter,120);
System.out.println("v3 volts using Class Adapter="+v3.getVolts());
System.out.println("v12 volts using Class Adapter="+v12.getVolts());
System.out.println("v120 volts using Class Adapter="+v120.getVolts());
}
private static Volt getVolt(SocketAdapter sockAdapter, int i) {
switch (i){
case 3: return sockAdapter.get3Volt();
case 12: return sockAdapter.get12Volt();
case 120: return sockAdapter.get120Volt();
default: return sockAdapter.get120Volt();
}
}
}
測試代碼的輸出結(jié)果是:
v3 volts using Class Adapter=3
v12 volts using Class Adapter=12
v120 volts using Class Adapter=120
v3 volts using Object Adapter=3
v12 volts using Object Adapter=12
v120 volts using Object Adapter=120
Adapter Design Pattern Example in JDK
在JDK中可以很容易找出幾個簡單的適配器模式的應用
java.util.Arrays#asList()
java.io.InputStreamReader(InputStream) (returns a Reader)
java.io.OutputStreamWriter(OutputStream) (returns a Writer)
使用場景
- 系統(tǒng)需要使用現(xiàn)有的類迂求,而這些類的接口不符合系統(tǒng)的需要碾盐。
- 想要建立一個可以重復使用的類,用于與一些彼此之間沒有太大關(guān)聯(lián)的一些類揩局,包括一些可能在將來引進的類一起工作毫玖。
- 需要一個統(tǒng)一的輸出接口,而輸入端的類型不可預知凌盯。