生活中的一些例子
在我們的日常生活中,對於介面卡,可以說是無處不在。例如我們平時使用的膝上型電腦,可能膝上型電腦的工作電壓是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中是使用的比較少的。
這兩種方式最重要的區別就是:
物件介面卡模式通過組合來實現介面卡功能,而類的介面卡模式通過多繼承或實現來實現介面卡功能。
介面卡模式的一些優缺點
感覺,優缺點沒什麼好說的,只有實際上去用過才能體會。反正最重要的優點就是將不相容的幾個介面通過一箇中間類,把他們進行適配,並且這個適配的過程對於客戶端來說是透明的,客戶端並不知道發生了啥,只知道它通過一個介面卡,就可以獲取到目標介面了。
至於缺點嘛,如果動不動就使用介面卡,那麼我覺得會使整個類系統變的有點零散,並且以後要重構了會更加複雜……
完
關注公我的眾號:苦逼的碼農,獲取更多原創文章,後臺回覆禮包送你一份時下熱門的資源大禮包。同時也感謝把文章介紹給更多需要的人