設計模式(六)—— 介面卡模式
1. 介紹
介面卡模式是把一個類的介面變換成客戶端的所期待的另一個介面,從而使原本因介面不匹配而無法在一起工作的兩個類能夠在一起工作。
2. 分類
介面卡模式有類的介面卡模式和物件的介面卡模式兩種形式。
2.1 類的介面卡模式
類的介面卡模式是把適配的類的API轉換成為目標類的API.
從上圖中可以看出:Target期待呼叫Request方法,而Adaptee並沒有(這就是所謂的不相容了)。
為使Target能夠使用Adaptee類裡的SpecificRequest方法,故提供一箇中間環節Adapter類(繼承Adaptee & 實現Target介面)
模式所涉及的角色有:
- 目標角色(Target):這就是所期待得到的介面
- 源角色(Adapee):現在需要適配的介面
- 介面卡角色(Adaper):介面卡類,把源介面轉換成目標介面
具體實現
(1)Target介面
public interface Target{
//這是源類Adaptee沒有的介面
public void Request();
}
(2)源類(Adaptee)
public class Adaptee { public void SpecificRequest() {} }
(3)介面卡類(Adapter)
//繼承Adaptee並實現Target
public class Adapter extends Adaptee implements Target {
//在介面卡中將SpecificRequest()方法轉化為Request()
@Override
public void Request() {
this.SpecificRequest();
}
}
(4)定義具體使用類,並通過Adapter類呼叫所需要的方法
public class AdapterPattern { public static void main(String[] args) { Target mAdapter = new Adapter(); mAdapter.Request(); } }
2.2 物件的介面卡模式
與類的介面卡模式相同,物件的介面卡模式也是把適配的類的API轉換成為目標類的API;與類的介面卡模式不同的是,物件的介面卡模式不是使用繼承關係連線到Adaptee類,而是使用委派關係連線到Adaptee類。
從上圖可以看出:Target期待呼叫Request方法,而Adaptee並沒有,因此提供一個包裝類Adapter,這個包裝類包裝了一個Adaptee的例項,從而能夠把Adaptee的API與Target類的API銜接起來。Adapter與Adaptee是委派關係,這決定了介面卡模式是物件介面卡模式。
具體實現
(1)Target介面
public interface Target{
//這是源類Adaptee沒有的介面
public void Request();
}
(2)源類(Adaptee)
public class Adaptee {
public void SpecificRequest() {}
}
(3)介面卡類(Adapter)
//不在繼承Adaptee類
public class Adapter implements Target {
//直接關聯被適配類
private Adaptee adaptee;
//可以通過建構函式傳入具體需要適配的被適配類物件
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void Request() {
//這裡使用委託方式完成轉換
this.adaptee.SpecificRequest();
}
}
(4)定義具體使用類,並通過Adapter類呼叫所需要的方法
public class AdapterPattern {
public static void main(String[] args) {
//需要先建立一個被適配類的物件作為引數
Target mAdapter = new Adapter(new Adaptee());
mAdapter.Request();
}
}
3. 介面卡模式的優缺點
優點
- 更好的複用性, 可以更好地複用現有的類
- 更好的擴充套件性, 在實現介面卡功能時,可以呼叫自己開發的功能,從而自然地擴充套件系統功能。
- 解耦性,將目標類和適配者類解耦
缺點
過多使用使用介面卡,會讓系統非常零亂,不易整體把握。
4. 對比類的介面卡模式和物件的介面卡模式
類的介面卡模式:
- 使用物件繼承方式,是靜態定義方式,由於直接繼承了Adaptee類,使得不能再和Adaptee的子類一起工作了;
- 類介面卡可以重新定義Adaptee的部分行為,相當於子類覆蓋父類的部分實現;
- 僅僅引入了一個物件,並不需要額外的引用來間接得到adapter。
物件介面卡模式:
- 使用物件組合的方式,是動態組合的方式,因此一個介面卡可以把多種不同的源適配到同一目標,換言之,同一個介面卡可以把源類和它的子類都是配到目標介面,因為物件介面卡採用的是物件組合關係,只要物件型別正確,是不是子類都無所謂。
- 物件介面卡要重新定義Adaptee的行為比較困難,這種情況下,需要定義Adaptee的子類來實現重新定義,然後讓介面卡組合子類。雖然重新定義Adaptee的行為比較困難,但是想要增加一些新的行為則很方便,而且新增加的的行為可同時適用於所有源。
- 物件介面卡需要額外的引用來間接得到Adapter。
建議儘量使用物件介面卡的實現方式,對用組合,少用繼承。當然,具體問題具體分析,根據需要來選用實現方式,最合適的才是最好的。