1. 程式人生 > 其它 >設計模式詳解——介面卡模式

設計模式詳解——介面卡模式

前言

今天我們來看另一個和包裝有關的設計模式——介面卡模式,和裝飾者模式比起來,它更像是一位無名耕耘者,隱身於溝渠之中,幹著髒活累活——轉換介面。用時下比較火的一個詞來比喻這種設計模式的話,那就是女裝大佬,這真的是介面卡模式最佳類比了,我相信你看完今天的所有內容,一定會明白的

介面卡模式

介面卡模式將一個類的介面,轉換成客戶期望的另一個介面,介面卡讓原本不相容的介面可以合作無間。

介面卡模式採用的設計原則是使用物件元件,以修改的介面包裝被適配者,這樣的好處是,被適配者的任何子類,都可以搭配介面卡使用。

採用介面卡模式之後:

要點

  • 介面卡模式主要是為了在不改變原有介面的基礎上,適配客戶新的介面
  • 當需要使用一個現有的類而其介面並不符合你的需要時,就使用介面卡模式
  • 介面卡有兩種形式:物件介面卡和類介面卡。類介面卡需要用到多重繼承
  • 介面卡將一個物件包裝起來以改變起介面;裝飾者將一個物件包裝起來以增加新的行為和屬性;而外觀模式將一群物件“包裝”起來以簡化其介面

示例程式碼

從網上搜了一些介面卡的示例,但是最後發現還是沒有《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();
    }

從程式碼中我們可以看到,這裡適配了鴨子的火雞像鴨子一樣執行了quackfly操作

執行結果:

總結

從上面的示例中,我們可以很清楚的看到,介面卡模式本質上就是型別的轉換,除了我們這裡的例子,日常生活中還有很多類似的例子,比如電腦顯示器VGAHDMI、用電裝置插頭轉換等:

雖然都是型別的包裝和轉換,但是介面卡模式和裝飾者模式是有本質區別的,裝飾者模式始終是同同一種類型的包裝和轉換,也就是說所有的包裝類於被包裝類,本質上都是同一種類型,但是在介面卡中,轉換和包裝的一定是不同的型別,比如火雞到鴨子。

最後引用一段話來結束今天的內容:

如果它走起來像只鴨子,叫起來像只鴨子,那麼它必定可能是一隻鴨子包裝了鴨子介面卡的火雞……