生活中的一些例子
在我們的日常生活中,對於適配器,可以說是無處不在。例如我們平時使用的筆記本電腦,可能筆記本電腦的工作電壓是20V,但我們一般的家庭用電是220V,這時候電腦在充電的時候就需要一個電源適配器來把220V的電腦轉化為20V的電壓了。這個電源適配器也別稱為充電器或變壓器。
又如,我們想用蘋果的充電線給安卓的手機充電時。由於兩者的接口不一樣,會導致充電口無法匹配。這時,我們就需要適配器,將安卓的充電接口轉化為蘋果的接口,這樣,就可以進行充電了。
上面說的兩個例子,就是今天我們要講的適配器模式。
適配器模定義
適配器模式把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。
在適配器模式中,存在兩種不同的模式結構:類的適配器模式和對象的適配器模式
對象的適配器模式
我們以上面的蘋果充電線給安卓手機充電的為例,如果是你來寫代碼,把他們進行兼容適配,你會怎么寫呢?
對於這個問題,我們首先先來看一下適配器模式中涉及到的三個角色:
1、Target(目標抽象類):目標抽象類定義客戶所需接口,可以是一個抽象類或接口,也可以是具體類。例如對於上面的第二個例子,客戶端的目標是要給只接受安卓充電口的安卓手機充電,所以我們的目標抽象類就是安卓充電線的接口。
2、Adaptee(適配者類):適配者即被適配的角色,它定義了一個已經存在的接口,這個接口需要適配,適配者類一般是一個具體類,包含了客戶希望使用的業務方法。例如上面蘋果充電線就是適配者類。
3、Adapter(適配器類):通過包裝一個需要適配的對象,把原接口轉換成目標接口。例如為了可以充電,我們需要一個適配器,使之一邊可以連接安卓充電的接口,一邊可以連接蘋果充電線的接口。
UML圖
下面我們用代碼來做個實例:
(1).Target類
public class Android {
public void isAndroid(){
System.out.println("這是一個只接受安卓充電線的插口");
}
}
(2).Adaptee類
public class Iphone {
public void isIphone(){
System.out.println("這是一個適配蘋果充電線的插口");
}
}
(3).Adapter類:把他們進行適配
/**
* 適配器,作為中間件,把他們進行適配
*/
public class Adapter extends Android{
private Iphone iphone;
public Adapter(Iphone iphone){
this.iphone = iphone;
}
@Override
public void isAndroid() {
iphone.isIphone();
}
}
(4).測試類
public class Demo {
public static void main(String[] args){
Android android = new Adapter(new Iphone());
//調用的是安卓的接口,但實際上
//確實一個可以接受蘋果充電器的接口
android.isAndroid();
}
}
(5).打印結果
這是一個適配蘋果充電線的插口
我們通過適配器的作用,就可以讓蘋果充電線給安卓手機充電了。。
對於這種對象的適配器模式,實際上就是通過一個適配器類,把目標類和需要被適配的類進行組合。所以適配器類Adapter一般需要繼承或實現Targert,並且還得持有Adaptee的實例引用。
類的適配器模式
除了對象的適配器模式,還有另外一種類的適配器模式。在這種模式中,Adapter不持有Adaptee的實例引用,而是直接繼承Adaptee類,然后再實現Target接口。或者直接繼承Adaptee類和Target類,但由於Java中不支持多重繼承,所以只能用實現Target的方式。
這也導致了在Jaca類的適配器模式中,Target必須是一個接口而不可以是抽象類和具體類(因為Java不支持多重繼承)。
把上面那個例子改寫一下,用類的適配器模式來實現:
(1).Target接口類
interface Android {
void isAndroid();
}
(2).Adaptee類
public class Iphone {
public void isIphone(){
System.out.println("這是一個適配蘋果充電線的接口");
}
}
(3).Adapter類:繼承Adaptee,實現Target
/**
* 適配器,把安卓手機的插口轉化為可以用蘋果充電線充電的接口
*/
public class Adapter extends Iphone implements Android{
@Override
public void isAndroid() {
//直接調用
isIphone();
}
}
(4).測試類
public class Demo {
public static void main(String[] args){
Android android = new Adapter();
android.isAndroid();
}
}
(5).打印結果
這是一個適配蘋果充電線的接口
對於這種類的適配器模式,在Java中是使用的比較少的。
這兩種方式最重要的區別就是:
對象適配器模式通過組合來實現適配器功能,而類的適配器模式通過多繼承或實現來實現適配器功能。
適配器模式的一些優缺點
感覺,優缺點沒什么好說的,只有實際上去用過才能體會。反正最重要的優點就是將不兼容的幾個接口通過一個中間類,把他們進行適配,並且這個適配的過程對於客戶端來說是透明的,客戶端並不知道發生了啥,只知道它通過一個適配器,就可以獲取到目標接口了。
至於缺點嘛,如果動不動就使用適配器,那么我覺得會使整個類系統變的有點零散,並且以后要重構了會更加復雜……
完
關注公我的眾號:苦逼的碼農,獲取更多原創文章,后台回復禮包送你一份時下熱門的資源大禮包。同時也感謝把文章介紹給更多需要的人