23種設計模式之介面卡模式
阿新 • • 發佈:2019-12-31
1、定義
將一個類的介面裝換成客戶希望的另外一個介面。介面卡模式使得原來由於介面不相容而不能一起工作的那些類可以一起工作。
2、類介面卡
2.1 模式結構
介面卡模式由三部分組成:
- Target(目標抽象類):目標抽象類定義客戶所需介面,可以是一個抽象類或介面,也可以是具體類。
- Adapter(介面卡類):介面卡可以呼叫另一個介面,作為一個轉換器,對Adaptee和Target進行適配,介面卡類是介面卡模式的核心。
- Adaptee(適配者類):適配者即被適配的角色,它定義了一個已經存在的介面,這個介面需要適配,適配者類一般是一個具體類,包含了客戶希望使用的業務方法。
2.2 例項
2.2.1 Android(Target抽象類)
public interface Android {
void isAndroid();
}
複製程式碼
2.2.2 Iphone(Adaptee類)
public class Iphone {
public void isIphone() {
System.out.println("這是一個適配蘋果充電線的介面");
}
}
複製程式碼
2.2.3 Adapter類
/**
* 將安卓手機的介面轉化為蘋果手機可用的充電介面
*/
public class Adapter extends Iphone implements Android {
@Override
public void isAndroid () {
isIphone();
}
}
複製程式碼
2.2.4 客戶端呼叫
public class Client {
public static void main(String[] args) {
Android android = new Adapter();
android.isAndroid();
}
}
複製程式碼
2.3 優缺點
2.3.1 優點
- 由於介面卡類是適配者的子類,因此可以在介面卡類中置換一些適配者的方法,使得介面卡的靈活性更強。
2.3.1 缺點
- 對於Java、C#等不支援多重類繼承的語言,一次最多隻能適配一個適配者類,不能同時適配多個適配者。
- 適配者類不能為最終類,如在Java中不能為final類,C#中不能為sealed類。
- 在Java、C#等語言中,類介面卡模式中的目標抽象類只能為藉口,不能為類,其使用有一定的侷限性。
3、物件介面卡
3.1 模式結構
角色與類介面卡模式一樣
3.2 例項
3.2.1 Android(Target抽象類)
public interface Android {
void isAndroid();
}
複製程式碼
3.2.2 Iphone(Adaptee類)
public class Iphone {
public void isIphone() {
System.out.println("這是一個適配蘋果充電線的介面");
}
}
複製程式碼
3.2.3 Adapter類
/**
* 將安卓手機的介面轉化為蘋果手機可用的充電介面
*/
public class Adapter implements Android {
private Iphone iphone;
public Adapter(Iphone iphone) {
this.iphone = iphone;
}
@Override
public void isAndroid() {
iphone.isIphone();
}
}
複製程式碼
3.2.4 客戶端呼叫
public class Client {
public static void main(String[] args) {
Android android = new Adapter(new Iphone());
android.isAndroid();
}
}
複製程式碼
3.3 優缺點
3.3.1 優點
- 一個物件介面卡可以把多個不同的適配者適配到同一個目標。
- 可以適配一個適配者的子類,由於介面卡和適配者之間是關聯關係,根據“里氏替換原則”,適配者的子類也可通過該介面卡進行適配。
3.3.2 缺點
- 與類介面卡模式相比,要在介面卡中置換適配者類的某些方法比較麻煩。如果一定要置換掉適配者類的一個或多個方法,可以先做一個適配者類的子類,將適配者類的方法置換掉,然後再把適配者類的子類當做真正的適配者進行適配,實現過程較為複雜。
4、預設介面卡
4.1 模式結構
預設介面卡由兩部分組成:
- Target(目標角色):目標介面。可以定義有很多方法,但這些方法不一定全都被使用者類所需要。
- Default Adapter(預設介面卡):預設適配模式的核心。它實現Target角色介面,為所以方法提供空的實現。
4.2 例項
4.2.1 Target
public interface SubjectTarget {
void learnChinese();
void learnEnglish();
void learnMath();
void learnBiological();
}
複製程式碼
4.2.2 Default Adapter
public abstract class SubjectAdapter implements SubjectTarget {
@Override
public void learnChinese() {
}
@Override
public void learnEnglish() {
}
@Override
public void learnMath() {
}
@Override
public void learnBiological() {
}
}
複製程式碼
4.2.3 客戶端呼叫
public class Client {
public static void main(String[] args) {
SubjectAdapter subjectAdapter = new SubjectAdapter() {
@Override
public void learnEnglish() {
System.out.println("學習英語使我快樂");
}
};
subjectAdapter.learnEnglish();
}
}
複製程式碼
5、使用場景
- 系統需要複用現有類,而該類的介面不符合系統的需求,可以使用介面卡模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。
- 想建立一個可以重複使用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作。
6、類介面卡和物件介面卡的權衡
- 靈活使用時:選擇物件介面卡。類介面卡使用物件繼承的方式,是靜態的定義方式;而物件介面卡使用物件組合的方式,是動態組合的方式。
- 需要同時配置源類和其子類:選擇物件介面卡。對於類介面卡,由於介面卡直接繼承了Adaptee,使得介面卡不能和Adaptee的子類一起工作,因為繼承是靜態的關係,當介面卡繼承了Adaptee後,就不可能再去處理Adaptee的子類;對於物件介面卡,一個介面卡可以把多種不同的源適配到同一個目標。換言之,同一個介面卡可以把源類和它的子類都適配到目標介面。因為物件介面卡採用的是物件組合的關係,只要物件型別正確,是不是子類都無所謂。
- 需要重新定義Adaptee的部分行為:選擇類介面卡。對於類介面卡,介面卡可以重定義Adaptee的部分行為,相當於子類覆蓋父類的部分實現方法。對於物件介面卡,要重定義Adaptee的行為比較困難,這種情況下,需要定義Adaptee的子類來實現重定義,然後讓介面卡組合子類。雖然重定義Adaptee的行為比較困難,但是想要增加一些新的行為則方便的很,而且新增加的行為可同時適用所有的源。
- 僅僅希望使用方便時:選擇類介面卡。對於類介面卡,僅僅引入了一個物件,並不需要額外的引用來間接得到Adaptee。對於物件介面卡,需要額外的引用來間接得到Adaptee。
7、在SpringMVC框架應用的原始碼剖析
8、介面卡的優缺點
8.1 優點
- 將目標類和適配者類解耦,通過引入一個介面卡類來重用現有的適配者類,而無須修改原有程式碼。
- 增加了類的透明性和複用性,將具體的實現封裝在適配者類中,對於客戶端類來說是透明的,而且提高了適配者的複用性。
- 靈活性和擴充套件性都非常好,通過使用配置檔案,可以很方便地更換介面卡,也可以在不修改原有程式碼的基礎上增加新的介面卡類,完全符合“開閉原則”。
8.2 缺點
- 過多地使用介面卡,會讓系統非常零亂,不易整體進行把握。比如,明明看到呼叫的是A介面,其實內部被適配成了B介面的實現,一個系統如果出現太多這種情況,無異於一場災難。因此如果不是很有必要,可以不適用介面卡,而是直接對系統進行重構。
- 對於類介面卡而言,由於Java至多繼承一個類,所以至多隻能適配一個適配者類,而且目標類必須是抽象類。
特別宣告:1、如若文中有錯之處,歡迎大神指出。 2、文章是參考網上一些大神的文章,自己整理出來的,如若有侵權,可聯絡我刪除。