Head First設計模式——介面卡和外觀模式
前言:為什麼要一次講解這兩個模式,說點騷話:因為比較簡單(*^_^*),其實是他們兩個有相似和有時候我們容易搞混概念。
講到這兩個設計模式與另外一個“裝飾者模式”也有相似,他們三個按照結構模式分類都屬於“結構性模式”,所有我們接下來就來看什麼是介面卡模式和外觀模式。
另外裝飾模式可以看我的另一篇博文→Head First設計模式——裝飾者模式。
一、介面卡模式
介面卡對應到我們現實生活中的例子,最典型的就是插頭介面介面卡,比如我們買的有些港版手機充電頭是圓形三角插頭,而大陸的三角電源插板插不進去港版的插頭。
這時候我們就會在某寶上買個轉接頭轉換一下,而這個轉接頭就是介面卡,用它來適配港版手機充電頭讓他能夠插入到我們的電源插板裡面。
在設計模式中這個介面卡是什麼,用程式如何表現,先讓我舉個栗子:我們有一隻鴨子,一隻雞,我們如何通過介面卡轉換鴨和雞。
鴨子有很多種,我們定義一個鴨子的介面,然後以綠頭鴨為例。關於這個綠頭鴨在策略模式也有用到,可以看看我另一篇綠頭鴨如何攪動策略模式→Head First設計模式——策略模式
public interface Duck { //叫 public void Quack(); //飛 public void Fly(); } public class GreenDuck : Duck { public void Fly() { Console.WriteLine("綠頭鴨,飛"); } public void Quack() { Console.WriteLine("綠頭鴨,呱呱叫"); } }
同樣我們定義一個雞的介面,和一隻母雞的類
public interface Chicken { //叫 public void Gobble(); //飛 public void Fly(); } public class Hen : Chicken { public void Gobble() { Console.WriteLine("母雞,咯咯叫"); } public void Fly() { Console.WriteLine("母雞,飛"); } }
鴨子和母雞的叫聲不一樣,現在我們讓母雞來冒充鴨子,利用介面卡模式如何做。 直接看程式碼吧
/// <summary> /// 母雞介面卡 /// 適配母雞讓它變成鴨子 /// </summary> public class HenAdapter : Duck { Chicken chicken; public HenAdapter(Chicken chicken) { this.chicken = chicken; } public void Quack() { //呼叫母雞咯咯叫 chicken.Gobble(); } public void Fly() { //呼叫母雞飛 chicken.Fly(); } }
測試母雞介面卡
如上我們使用母雞介面卡將母雞適配成了鴨子,鴨子也可以用介面卡將鴨子適配成母雞,介面卡模式定義:
介面卡模式:將一個類的介面,裝換成客戶期望的另一個介面。介面卡讓原本介面不相容的類可以合作無間。
與介面卡看起來相似的裝飾者模式是包裝物件的行為或責任,裝飾者被包裝後可能會繼續被包裝,他們不裝換介面,而介面卡則一定會進行介面的轉換。
適配的工作是將一個介面轉換成另外一個介面,雖然大多數介面卡採取的例子都是讓一個介面卡包裝一個被適配者,但是有時候我們需要讓一個介面卡包裝多個被適配者。
而這實際又涉及到另外一個模式,就是外觀模式,我們常常將介面卡模式和外觀模式混為一談,那接著就來講解外觀模式。
二、外觀模式
外觀模式以家庭影院為例,家庭影院有許多元件構成,比如:顯示屏、DVD、音響、燈光等等。
當我們要看電影的時候要開啟顯示屏,開啟DVD,開啟音響,關閉燈光等一系列動作,將這些動作寫成類方法的呼叫
Screen screen = new Screen(); DVD dvd = new DVD(); SoundEngineer sound = new SoundEngineer(); Light light = new Light(); screen.Down(); dvd.PlayDVD(); sound.TurnOn(); light.TurnOff();
可以看到每次我們要使用就要呼叫一篇這些方法,如果要關閉呢,我們也需要呼叫一篇。而我們正需要的就是一個外觀:通過實現一個提供更合理的介面的外觀類。
還是看程式碼吧
public class HomeThreaterFacade { Screen screen; DVD dvd; SoundEngineer sound; Light light; public HomeThreaterFacade(Screen screen, DVD dvd, SoundEngineer sound, Light light) { this.screen = screen; this.dvd = dvd; this.sound = sound; this.light = light; } public void WatchMovie() { Console.WriteLine("開始播放電影......"); screen.Down(); dvd.PlayDVD(); sound.TurnOn(); light.TurnOff(); } }
由於其他類比較簡單就是一個列印輸出,我就不列出來了,還有關閉方法同理也很簡單就實現了。
還是測試一下效果:
外觀模式定義
外觀模式:提供了一個統一的介面,用來訪問子系統中的一群介面。外觀定義了一個高層介面,讓子系統更容易使用。
外觀模式遵循了一個設計原則
最少知識原則:之和你的密友談話。
這個原則希望我們在設計中,不要讓太多的類耦合在一起,免得修改系統中一部分,會影響其他部分。而外觀模式讓使用者不用關心全部子系統元件,讓客戶變得簡單有彈性。我們可以在不影響客戶的情況下升級外觀模式裡的元件,而客戶只有一個朋友,也就是外觀模式。
三、介面卡模式與外觀模式區別
從上面例子我們也許會覺得介面卡和外觀模式之間的差異在於:介面卡包裝一個類,而外觀可以代表許多類
但是實際它們的本質和作用並不是在於包裝多少類,介面卡模式將一個或多個介面變成客戶期望的一個介面,我們一般適配一個類,但是特殊需求也可以適配多個類來提供一個介面。類是地,一個外觀也可以只爭對一個複雜介面的類提供簡化介面。兩中模式的差異在於他們的意圖。介面卡模式意圖是將介面裝換成不同介面,外觀的意圖是簡化接