設計模式詳解——介面卡模式
前言
今天我們來看另一個和包裝有關的設計模式——介面卡模式,和裝飾者模式比起來,它更像是一位無名耕耘者,隱身於溝渠之中,幹著髒活累活——轉換介面。用時下比較火的一個詞來比喻這種設計模式的話,那就是女裝大佬,這真的是介面卡模式最佳類比了,我相信你看完今天的所有內容,一定會明白的
介面卡模式
介面卡模式將一個類的介面,轉換成客戶期望的另一個介面,介面卡讓原本不相容的介面可以合作無間。
介面卡模式採用的設計原則是使用物件元件,以修改的介面包裝被適配者,這樣的好處是,被適配者的任何子類,都可以搭配介面卡使用。
採用介面卡模式之後:
要點
- 介面卡模式主要是為了在不改變原有介面的基礎上,適配客戶新的介面
- 當需要使用一個現有的類而其介面並不符合你的需要時,就使用介面卡模式
- 介面卡有兩種形式:物件介面卡和類介面卡。類介面卡需要用到多重繼承
- 介面卡將一個物件包裝起來以改變起介面;裝飾者將一個物件包裝起來以增加新的行為和屬性;而外觀模式將一群物件“包裝”起來以簡化其介面
示例程式碼
從網上搜了一些介面卡的示例,但是最後發現還是沒有《Head First
設計模式》中的簡單,所以最後我還是用了書上的示例。
示例的場景是這樣的:假設客戶需要一隻鴨子,但是我們手裡只有火雞,這時候為了滿足客戶的需求,我們必須通過介面卡將火雞轉換成鴨子。
下面就是整個實現過程:
原始系統介面
首選我們拿到鴨子的介面,其中有兩個方法,要給是鳴叫,一個是飛
public interface Duck {
void quack();
void fly();
}
介面實現類
這個是鴨子的實現,這是僅僅是為了後期測試。因為我們現在沒有這個實現,所以後面要適配這樣一個物件。
public class MallardDuck implements Duck { @Override public void quack() { System.out.println("quack"); } @Override public void fly() { System.out.println("I'm flying"); } }
被適配物件介面
這個是我們火雞的原始介面,也就是我們要適配成鴨子的火雞的基類,也有兩個方法,一個是鳴叫,一個是飛。
public interface Turkey {
void gobble();
void fly();
}
火雞的實現類:
public class WildTurkey implements Turkey {
@Override
public void gobble() {
System.out.println("gobble gobble");
}
@Override
public void fly() {
System.out.println("I'm flying a short distance");
}
}
介面卡實現
這裡就是火雞適配鴨子的介面卡,首先它要實現鴨子的介面,然後我們定義一個火雞屬性,用於接收我們的火雞例項,再然後我們將火雞的鳴叫和飛的方法分別封裝到鴨子的對應方法,因為要是一直飛,火雞是普魯普魯飛,所以要多次飛。至此 ,火雞適配鴨子的適配操作就完成了,下面我們測試下。
public class TurkeyAdapter implements Duck {
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
@Override
public void quack() {
turkey.gobble();
}
@Override
public void fly() {
for (int i = 0; i < 5; i++) {
turkey.fly();
}
}
}
測試程式碼
這裡我們分別建立了鴨子、火雞和適配了鴨子的火雞的示例,演示他們的執行過程:
@Test
public void testDuck() {
MallardDuck duck = new MallardDuck();
WildTurkey turkey = new WildTurkey();
TurkeyAdapter turkeyAdapter = new TurkeyAdapter(turkey);
System.out.println("火雞:");
turkey.gobble();
turkey.fly();
System.out.println("=============\n綠頭鴨:");
duck.quack();
duck.fly();
System.out.println("=============\n火雞適配的鴨子:");
turkeyAdapter.quack();
turkeyAdapter.fly();
}
從程式碼中我們可以看到,這裡適配了鴨子的火雞像鴨子一樣執行了quack
和fly
操作
執行結果:
總結
從上面的示例中,我們可以很清楚的看到,介面卡模式本質上就是型別的轉換,除了我們這裡的例子,日常生活中還有很多類似的例子,比如電腦顯示器VGA
轉HDMI
、用電裝置插頭轉換等:
雖然都是型別的包裝和轉換,但是介面卡模式和裝飾者模式是有本質區別的,裝飾者模式始終是同同一種類型的包裝和轉換,也就是說所有的包裝類於被包裝類,本質上都是同一種類型,但是在介面卡中,轉換和包裝的一定是不同的型別,比如火雞到鴨子。
最後引用一段話來結束今天的內容:
如果它走起來像只鴨子,叫起來像只鴨子,那麼它
必定可能是一隻鴨子包裝了鴨子介面卡的火雞……