設計模式之門面模式20170728
結構型設計模式之門面模式:
一、含義
門面模式也叫做外觀模式,是一種比較常用的封裝模式,其定義如下:
要求一個子系統的外部與其內部的通信必須通過一個統一的對象進行,門面模式提供一個高層次的接口,使得子系統更易於使用。
通俗來說,門面模式註重"統一的對象",也就是提供一個訪問子系統的接口,除了這個接口不允許有任何訪問子系統的行為發生。也就是說,門面對象是外界訪問子系統內部的唯一通道。
二、代碼說明
1.主要有兩個角色
1)門面角色
客戶端可以調用這個角色的方法。此角色知曉子系統的所有功能和責任。一般情況下,本角色會將所有從客戶端發來的請求委派到相應的子系統去,也就是說該角色沒有實際的業務邏輯,只是一個委托類。
2)子系統角色
可以同時有一個或者多個子系統。每一個子系統都不是一個單獨的類,而是一個類的集合。子系統並不知道門面的存在。對於子系統而言,門面僅僅是另外一個客戶端而已。
2.在用C實現過程中也是參考這種思想,以寫信過程舉例,具體實現如下:
1)門面模式使用場景:
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------FacadePatternUsage.c4 * File Module : FacadePatternUsage.c 5 * Description : 門面模式的使用 6 7 [email protected]:/work/projects/test/DesignPatterns/FacadePattern$ gcc -o FacadePatternUsage LetterProcess.c Police.c FacadePattern.c FacadePatternUsage.c 8 [email protected]:/work/projects/test/DesignPatterns/FacadePattern$ ./FacadePatternUsage9 填寫信的內容......Happy Road NO.666,God Province,Heaven 10 填寫收件人地址及姓名......Hello,It‘s me,do you know who I am?I‘m your old lover,I‘d like to ...... 11 信件已經檢查過了...... 12 把信放到信封中...... 13 郵遞信件...... 14 15 * Created : 2017.07.27. 16 * Author : Yu Weifeng 17 * Function List : 18 * Last Modified : 19 * History : 20 ******************************************************************************/ 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include "FacadePattern.h" 25 26 27 28 29 /***************************************************************************** 30 -Fuction : main 31 -Description : 32 -Input : 33 -Output : 34 -Return : 35 * Modify Date Version Author Modification 36 * ----------------------------------------------- 37 * 2017/07/27 V1.0.0 Yu Weifeng Created 38 ******************************************************************************/ 39 int main(int argc,char **argv) 40 { 41 char *strContent="Happy Road NO.666,God Province,Heaven"; 42 char *strAddress="Hello,It‘s me,do you know who I am?I‘m your old lover,I‘d like to ......"; 43 g_tModernPostOffice.SendLetter(strContent,strAddress); 44 return 0; 45 }
2)被調用者:
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : FacadePattern.c 5 * Description : 門面模式 6 本文件是現代郵局的具體實現(門面角色) 7 以寫信過程舉例 8 9 * Created : 2017.07.27. 10 * Author : Yu Weifeng 11 * Function List : 12 * Last Modified : 13 * History : 14 ******************************************************************************/ 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include "FacadePattern.h" 19 #include "LetterProcess.h" 20 #include "Police.h" 21 22 static T_Police g_tPolice=newPolice; 23 static T_LetterProcess g_tLetterProcess=newLetterProcess; 24 25 void ModernPostOfficeSendLetter(char *i_strContent,char *i_strAddress); 26 const T_ModernPostOffice g_tModernPostOffice={ 27 .SendLetter=ModernPostOfficeSendLetter 28 29 }; 30 31 /***************************************************************************** 32 -Fuction : ModernPostOfficeSendLetter 33 -Description : 公有函數 34 -Input : 35 -Output : 36 -Return : 37 * Modify Date Version Author Modification 38 * ----------------------------------------------- 39 * 2017/07/27 V1.0.0 Yu Weifeng Created 40 ******************************************************************************/ 41 void ModernPostOfficeSendLetter(char *i_strContent,char *i_strAddress) 42 { 43 g_tLetterProcess.WriteContent(i_strContent); 44 g_tLetterProcess.FillEnvelope(i_strAddress); 45 g_tPolice.CheckLetter(); 46 g_tLetterProcess.LetterIntoEnvelope(); 47 g_tLetterProcess.SendLetter(); 48 }FacadePattern.c
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : FacadePattern.h 5 * Description : 門面模式 6 7 * Created : 2017.07.27. 8 * Author : Yu Weifeng 9 * Function List : 10 * Last Modified : 11 * History : 12 ******************************************************************************/ 13 #ifndef FACADE_PATTERN_H 14 #define FACADE_PATTERN_H 15 16 17 typedef struct ModernPostOffice//門面角色 18 { 19 void (*SendLetter)(char *i_strContext,char *i_strAddress); 20 21 }T_ModernPostOffice;//實現封裝(封裝寫信過程,內部過程對高層透明,高內聚) 22 23 const T_ModernPostOffice g_tModernPostOffice; 24 25 #endifFacadePattern.h
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : LetterProcess.c 5 * Description : 門面模式 6 本文件是寫信過程的具體實現 7 8 * Created : 2017.07.27. 9 * Author : Yu Weifeng 10 * Function List : 11 * Last Modified : 12 * History : 13 ******************************************************************************/ 14 #include"stdio.h" 15 #include"malloc.h" 16 #include"stdlib.h" 17 #include"string.h" 18 #include"LetterProcess.h" 19 20 21 /***************************************************************************** 22 -Fuction : WriteContent 23 -Description : 公有函數 24 -Input : 25 -Output : 26 -Return : 27 * Modify Date Version Author Modification 28 * ----------------------------------------------- 29 * 2017/07/27 V1.0.0 Yu Weifeng Created 30 ******************************************************************************/ 31 void WriteContent(char *i_strContent) 32 { 33 printf("填寫信的內容......%s\r\n",i_strContent); 34 } 35 36 /***************************************************************************** 37 -Fuction : FillEnvelope 38 -Description : 公有函數 39 -Input : 40 -Output : 41 -Return : 42 * Modify Date Version Author Modification 43 * ----------------------------------------------- 44 * 2017/07/27 V1.0.0 Yu Weifeng Created 45 ******************************************************************************/ 46 void FillEnvelope(char *i_strAddress) 47 { 48 printf("填寫收件人地址及姓名......%s\r\n",i_strAddress); 49 } 50 51 /***************************************************************************** 52 -Fuction : LetterIntoEnvelope 53 -Description : 公有函數 54 -Input : 55 -Output : 56 -Return : 57 * Modify Date Version Author Modification 58 * ----------------------------------------------- 59 * 2017/07/27 V1.0.0 Yu Weifeng Created 60 ******************************************************************************/ 61 void LetterIntoEnvelope() 62 { 63 printf("把信放到信封中......\r\n"); 64 } 65 66 /***************************************************************************** 67 -Fuction : SendLetter 68 -Description : 公有函數 69 -Input : 70 -Output : 71 -Return : 72 * Modify Date Version Author Modification 73 * ----------------------------------------------- 74 * 2017/07/27 V1.0.0 Yu Weifeng Created 75 ******************************************************************************/ 76 void SendLetter() 77 { 78 printf("郵遞信件......\r\n"); 79 }LetterProcess.c
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : LetterProcess.h 5 * Description : 門面模式 6 寫信過程 7 8 * Created : 2017.07.27. 9 * Author : Yu Weifeng 10 * Function List : 11 * Last Modified : 12 * History : 13 ******************************************************************************/ 14 #ifndef LETTER_PROCESS_H 15 #define LETTER_PROCESS_H 16 17 18 typedef struct LetterProcess 19 { 20 void (*WriteContent)(char *i_strContent); 21 void (*FillEnvelope)(char *i_strAddress); 22 void (*LetterIntoEnvelope)(); 23 void (*SendLetter)(); 24 }T_LetterProcess; 25 26 27 void WriteContent(char *i_strContent); 28 void FillEnvelope(char *i_strAddress); 29 void LetterIntoEnvelope(); 30 void SendLetter(); 31 #define newLetterProcess {WriteContent,FillEnvelope,LetterIntoEnvelope,SendLetter} 32 33 34 35 36 37 38 39 40 #endifLetterProcess.h
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : Police.c 5 * Description : 門面模式 6 本文件是警察的具體實現 7 8 * Created : 2017.07.27. 9 * Author : Yu Weifeng 10 * Function List : 11 * Last Modified : 12 * History : 13 ******************************************************************************/ 14 #include"stdio.h" 15 #include"malloc.h" 16 #include"stdlib.h" 17 #include"string.h" 18 #include"Police.h" 19 20 /***************************************************************************** 21 -Fuction : CheckLetter 22 -Description : 公有函數 23 -Input : 24 -Output : 25 -Return : 26 * Modify Date Version Author Modification 27 * ----------------------------------------------- 28 * 2017/07/27 V1.0.0 Yu Weifeng Created 29 ******************************************************************************/ 30 void CheckLetter() 31 { 32 printf("信件已經檢查過了......\r\n"); 33 }Police.c
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : Police.h 5 * Description : 門面模式 6 警察(檢查信件) 7 * Created : 2017.07.27. 8 * Author : Yu Weifeng 9 * Function List : 10 * Last Modified : 11 * History : 12 ******************************************************************************/ 13 #ifndef POLICE_H 14 #define POLICE_H 15 16 17 typedef struct Police 18 { 19 void (*CheckLetter)(); 20 21 }T_Police; 22 23 void CheckLetter(); 24 #define newPolice {CheckLetter} 25 26 27 #endifPolice.h
3)執行結果:
[email protected]:/work/projects/test/DesignPatterns/FacadePattern$ gcc -o FacadePatternUsage LetterProcess.c Police.c FacadePattern.c FacadePatternUsage.c
[email protected]:/work/projects/test/DesignPatterns/FacadePattern$ ./FacadePatternUsage
填寫信的內容......Happy Road NO.666,God Province,Heaven
填寫收件人地址及姓名......Hello,It‘s me,do you know who I am?I‘m your old lover,I‘d like to ......
信件已經檢查過了......
把信放到信封中......
郵遞信件......
4)詳細代碼:
https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/StructuralDesignPatterns/FacadePattern
三、使用場景
1.為一個復雜的模塊或子系統提供一個供外界訪問的接口
2.子系統相對獨立---外界對子系統的訪問只要黑箱操作即可
3.預防低水平人員帶來的風險擴散
為降低低水平人員的代碼質量對整體項目的影響風險,一般的做法就是讓其只能在指定的子系統中開發,然後再提供門面接口進行訪問操作。
四、優點
1.減少系統的相互依賴
所有的依賴都是對門面對象的依賴,與子系統無關
2.提高了靈活性
依賴少了,靈活性自然提高了。不管子系統內部如何變化,只要不影響到門面模式即可。
3.提高安全性
想外界可以訪問子系統的哪些業務就開通哪些邏輯,不在門面上開通的方法,外界無法訪問。
五、缺點
門面模式最大的缺點就是不符合開閉原則,對修改關閉,對擴展開放。一旦系統投產後發現有一個小錯誤,唯一能做的就是修改門面角色的代碼,這個風險相當大,所以就需要在設計的時候慎之又慎,多思考即便才會有好收獲。
六、門面模式的註意事項
1.一個子系統可以有多個門面
一般情況下,一個子系統只要有一個門面足夠在什麽情況下一個子系統有多個門面呢?以下列舉了幾個:
1)門面已經龐大到不能忍受的程度
2)子系統可以提供不同訪問路徑
比如有兩個門面,一個可以完整的訪問所有業務邏輯,另一個只能訪問子系統的某一個方法
2.門面不參與子系統內的業務邏輯
門面對象只是提供一個訪問子系統的一個路徑而已,它不應該也不能參與具體的業務邏輯,否則就會產生一個倒依賴的問題:子系統必須依賴門面才能被訪問,這是設計上一個嚴重錯誤,不僅違反了單一職責原則,同時也破壞了系統的封裝性。
在門面模式中,門面角色應該是穩定的,它不應該經常變化(變化肯定就不能保證穩定運行了),一個系統一旦投入運行它就不應該被改變,它是一個系統對外的接口。但是,業務邏輯是會經常變化的,所以我們把變化的封裝在子系統內部,這樣,對外界的訪問者來說,都還是同一個門面,同樣的方法,也就是穩定的。
七、與其他模式的區別
1、門面模式與中介者模式的區別:
門面模式為復雜的子系統提供一個統一的訪問界面,它定義的是一個高層接口,該接口使得子系統更加容易使用,避免外部模塊深入到子系統內部而產生與子系統內部細節耦合的問題。
中介者模式使用一個中介對象來封裝一系列同時對象的交互行為,它使各對象之間不再顯式地引用,從而使其耦合松散,建立一個擴展的應用架構。
具體來說,門面模式是以封裝和隔離為主要任務,而中介者模式則是以調和同事類之間的關系為主,因為要調和,所以具有了部分的業務邏輯控制。兩者的主要區別如下:
1)功能區別
門面模式只是增加了一個門面,它對子系統來說沒有增加任何的功能,子系統若脫離門面模式是完全可以獨立運行的。
而中介者模式則增加了業務功能,它把各個同事類中的原有耦合關系移植到了中介者,同事類不可能脫離中介者而獨立存在,除非是想增加系統的復雜性和降低擴展性。
2)知曉狀態不同
對門面模式來說,子系統不知道有門面存在,而對中介者來說,每個同事類都知道中介者存在,因為要依靠中介者調和同時之間的關系,他們對中介者非常了解。
3)封裝程度不同
門面模式是一種簡單的封裝,所有的請求處理都委托給子系統完成,而中介者模式則需要有一個中心,有中心協調同事類完成,並且中心本身也完成部分業務,它屬於更進一步的業務功能封裝
2、門面模式與其他包裝模式的區別:
自己不處理讓其他人處理,這種類型的模式定義一個名字,叫做包裝模式。包裝模式包括:裝飾模式、適配器模式、門面模式、代理模式、橋梁模式。
5個包裝模式都是通過委托的方式對一個對象或一系列對象施行包裝,有了包裝,設計的系統才更加靈活、穩定,並且極具擴展性。從實現的角度來看,它們都是代理的一種具體表現形式,它們在使用場景上的區別如下:
1)代理模式主要用在不希望展示一個對象內部細節的場景中,此外,代理模式還可以用在一個對象的訪問需要限制的場景中。
2)裝飾模式是一種特殊的代理模式,它倡導的是在不改變接口的前提下為對象增強功能,或者動態添加額外職責。就擴展性而言,它比子類更靈活。
3)適配器模式的主要意圖是接口轉換,把一個對象的接口轉換成系統希望的另外一個接口。這裏的系統指的不僅僅是一個應用,也可能是某個環境,比如通過接口轉換可以屏蔽外界接口,以免外界接口深入系統內部,從而提高系統的穩定性和可靠性
4)橋梁模式是在抽象層產生耦合,解決的是自行擴展的問題,它可以使兩個有耦合關系的對象互不影響地擴展。
5)門面模式是一個粗粒度的封裝,它提供一個方便訪問子系統的接口,不具有任何的業務邏輯,僅僅是一個訪問復雜系統的快速通道,沒有它,子系統照樣運行。
設計模式之門面模式20170728