Head First設計模式之外觀模式
阿新 • • 發佈:2017-07-27
實現 add ads important pac mar private 入口 summary
一、定義
外觀模式提供了一個統一的接口,用來訪問子系統中的一群接口。外觀定義了一個高層接口,讓子系統更容易使用。
外觀模式不只是簡化了接口,也將客戶從組件的子系統中解耦。
外觀和適配器可以包裝許多類,但是外觀強調的是簡化接口,而適配器是為了將接口轉換成不同的接口。
二、結構
外觀角色(Facade):是模式的核心,他被客戶client角色調用,知道各個子系統的功能。同時根據客戶角色已有的需求預訂了幾種功能組合
子系統角色(Subsystem classes):實現子系統的功能,並處理由Facade對象指派的任務。對子系統而言,facade和client角色是未知的,沒有Facade的任何相關信息;即沒有指向Facade的實例。 客戶角色(client):調用facade角色獲得完成相應的功能。
三、實現
class Program { static void Main(string[] args) { //----晚上下班回到家---- //開燈光 ILight light = new Light(); light.On(); //看電視 ITV tv = new TV(); tv.On();//-----睡覺----- //關燈光 light.Off(); //關電視 tv.Off(); Console.WriteLine("==== 最近有錢換智能家居了 ===="); ISmartHome smarthome = new SmartHome(); //----晚上下班回到家---- smarthome.On(); //-----睡覺----- smarthome.Off(); } }/// <summary> /// 燈光接口 /// </summary> public interface ILight { /// <summary> /// 開燈 /// </summary> void On(); /// <summary> /// 關燈 /// </summary> void Off(); } /// <summary> /// 燈光接口實現類 /// </summary> public class Light : ILight { public void On() { Console.WriteLine("打開燈"); } public void Off() { Console.WriteLine("關閉燈"); } } /// <summary> /// 電視接口 /// </summary> public interface ITV { /// <summary> /// 開機 /// </summary> void On(); /// <summary> /// 關機 /// </summary> void Off(); } /// <summary> /// 智能家居總開關接口 /// </summary> public interface ISmartHome { /// <summary> /// 開燈 /// </summary> void On(); /// <summary> /// 關燈 /// </summary> void Off(); } public class TV : ITV { public void On() { Console.WriteLine("打開電視"); } public void Off() { Console.WriteLine("關閉電視"); } } public class SmartHome : ISmartHome { private ILight light = new Light(); private ITV tv = new TV(); public void On() { light.On(); tv.On(); } public void Off() { light.Off(); tv.Off(); } }
四、適用場景
在以下情況下可以考慮使用外觀模式: (1)設計初期階段,應該有意識的將不同層分離,層與層之間建立外觀模式。 (2) 開發階段,子系統越來越復雜,增加外觀模式提供一個簡單的調用接口。 (3) 維護一個大型遺留系統的時候,可能這個系統已經非常難以維護和擴展,但又包含非常重要的功能,為其開發一個外觀類,以便新系統與其交互。
五、優缺點
優點:
1)對客戶屏蔽子系統組件,減少了客戶處理的對象數目並使得子系統使用起來更加容易。通過引入外觀模式,客戶代碼將變得很簡單,與之關聯的對象也很少。 2)實現了子系統與客戶之間的松耦合關系,這使得子系統的組件變化不會影響到調用它的客戶類,只需要調整外觀類即可。 3)降低了大型軟件系統中的編譯依賴性,並簡化了系統在不同平臺之間的移植過程,因為編譯一個子系統一般不需要編譯所有其他的子系統。一個子系統的修改對其他子系統沒有任何影響,而且子系統內部變化也不會影響到外觀對象。 4)只是提供了一個訪問子系統的統一入口,並不影響用戶直接使用子系統類。缺點:
1) 不能很好地限制客戶使用子系統類,如果對客戶訪問子系統類做太多的限制則減少了可變性和靈活性。 2) 在不引入抽象外觀類的情況下,增加新的子系統可能需要修改外觀類或客戶端的源代碼,違背了“開閉原則”。
六、模式擴展
一個系統有多個外觀類: 在外觀模式中,通常只需要一個外觀類,並且此外觀類只有一個實例,換言之它是一個單例類。在很多情況下為了節約系統資源,一般將外觀類設計為單例類。當然這並不意味著在整個系統裏只能有一個外觀類,在一個系統中可以設計多個外觀類,每個外觀類都負責和一些特定的子系統交互,向用戶提供相應的業務功能。 不要試圖通過外觀類為子系統增加新行為: 不要通過繼承一個外觀類在子系統中加入新的行為,這種做法是錯誤的。外觀模式的用意是為子系統提供一個集中化和簡化的溝通渠道,而不是向子系統加入新的行為,新的行為的增加應該通過修改原有子系統類或增加新的子系統類來實現,不能通過外觀類來實現。 外觀模式與迪米特法則: 外觀模式創造出一個外觀對象,將客戶端所涉及的屬於一個子系統的協作夥伴的數量減到最少,使得客戶端與子系統內部的對象的相互作用被外觀對象所取代。外觀類充當了客戶類與子系統類之間的“第三者”,降低了客戶類與子系統類之間的耦合度,外觀模式就是實現代碼重構以便達到“迪米特法則”要求的一個強有力的武器。抽象外觀類的引入:
外觀模式最大的缺點在於違背了“開閉原則”,
當增加新的子系統或者移除子系統時需要修改外觀類,可以通過引入抽象外觀類在一定程度上解決該問題,客戶端針對抽象外觀類進行編程。對於新的業務需求,不修改原有外觀類,而對應增加一個新的具體外觀類,由新的具體外觀類來關聯新的子系統對象,同時通過修改配置文件來達到不修改源代碼並更換外觀類的目的。UML:
參考:
http://blog.csdn.net/hguisu/article/details/7533759
http://www.cnblogs.com/JsonShare/p/7121383.html
歡迎閱讀本系列文章:Head First設計模式之目錄
Head First設計模式之外觀模式