title: java-23種設計模式-門面模式(外觀模式) catalog: true date: 2018-11-28 15:07:16 subtitle: header-img: tags:
1 介紹
外觀模式(Facade),他隱藏了系統的複雜性,並向客戶端提供了一個可以訪問系統的介面。這種型別的設計模式屬於結構性模式。為子系統中的一組介面提供了一個統一的訪問介面,這個介面使得子系統更容易被訪問或者使用。
2 角色和使用場景
簡單來說,該模式就是把一些複雜的流程封裝成一個介面供給外部使用者更簡單的使用。這個模式中,設計到3個角色。
-
門面角色:外觀模式的核心。它被客戶角色呼叫,它熟悉子系統的功能。內部根據客戶角色的需求預定了幾種功能的組合。
-
子系統角色:實現了子系統的功能。它對客戶角色和Facade時未知的。它內部可以有系統內的相互互動,也可以由供外界呼叫的介面。
-
客戶角色:通過呼叫Facede來完成要實現的功能。
2.1 使用場景
-
為複雜的模組或子系統提供外界訪問的模組;
-
子系統相互獨立;
-
在層析結構中,可以使用外觀模式定義系統的每一層的入口。
3 程式碼例項
3.1 原始狀態
一寫信為例,比如給女朋友寫情書什麼的,寫信 的過程大家都還記得吧,先寫信的內容,然後寫信封,然後把信放到信封中,封好,投遞到信箱中進行郵 遞,這個過程還是比較簡單的,雖然簡單,這四個步驟都是要跑的呀,信多了還是麻煩,比如到了情人節, 為了大海撈針,給十個女孩子發情書,都要這樣跑一遍,你不要累死,更別說你要發個廣告信啥的,一下 子發 1 千萬封郵件,那不就完蛋了?那怎麼辦呢?還好,現在郵局開發了一個新業務,你只要把信件的必 要資訊告訴我,我給你發,我來做這四個過程,你就不要管了,只要把信件交給我就成了。
類圖:
先看寫信的過程介面,定義了寫信的四個步驟:
public interface LetterProcess {
//定義一個寫信的過程
//首先要寫信的內容
public void writeContext(String context);
//其次寫信封
public void fillEnvelope(String address);
//把信放到信封裡
public void letterInotoEnvelope();
//然後郵遞
public void sendLetter();
}
複製程式碼
寫信過程的具體實現:
public class LetterProcessImpl implements LetterProcess{
//寫信
@Override
public void writeContext(String context) {
System.out.println("填寫信的內容...." + context);
}
//在信封上填寫必要的資訊
@Override
public void fillEnvelope(String address) {
System.out.println("填寫收件人地址及姓名...." + address);
}
//把信放到信封中,並封好
@Override
public void letterInotoEnvelope() {
System.out.println("把信放到信封中....");
}
//塞到郵箱中,郵遞
@Override
public void sendLetter() {
System.out.println("郵遞信件...");
}
}
複製程式碼
然後就有人開始用這個過程寫信了:
public interface LetterProcess {
//定義一個寫信的過程
//首先要寫信的內容
public void writeContext(String context);
//其次寫信封
public void fillEnvelope(String address);
//把信放到信封裡
public void letterInotoEnvelope();
//然後郵遞
public void sendLetter();
}
複製程式碼
3.2 使用門面模式
那這個過程與高內聚的要求相差甚遠,你想,你要知道這四個步驟,而且還要知道這四個步驟的順序, 一旦出錯,信就不可能郵寄出去,那我們如何來改進呢?先看類圖:
這就是門面模式,還是比較簡單的,Sub System(子系統) 比較複雜,為了讓呼叫者更方便的呼叫,就對 Sub System 進行了封裝,增加了一個門面,Client 呼叫時,直接呼叫門面的方法就可以了,不用瞭解具體的實現方法 以及相關的業務順序,我們來看程式的改變,LetterProcess 介面和實現類都沒有改變,只是增加了一個 ModenPostOffice 類,我們這個 java 程式清單如下:
public class ModenPostOffice {
private LetterProcess letterProcess = new LetterProcessImpl();
//寫信,封裝,投遞,一體化了
public void sendLetter(String context, String address) {
//幫你寫信
letterProcess.writeContext(context);
//寫好信封
letterProcess.fillEnvelope(address);
//把信放到信封中
letterProcess.letterInotoEnvelope();
//郵遞信件
letterProcess.sendLetter();
}
}
複製程式碼
個類是什麼意思呢,就是說現在有一個提供了一種新型的 服務,客戶只要把信的內容以及收信地址給他們,他們就會把信寫好,封好,併傳送出去,這種服務提出 時大受歡迎呀,這簡單呀,客戶減少了很多工作,那我們看看客戶是怎麼呼叫的,Client.java 的程式清單 如下:
public class Client {
public static void main(String[] args) {
//現代化的郵局,有這項服務
ModenPostOffice hellRoadPostOffice = new ModenPostOffice();
//你只要把信的內容和收信人地址給他,他會幫你完成一系列的工作;
String address = "Happy Road No. 666,God Province,Heaven"; //定義一個地址
String context = "Hello,It's me,do you know who I am? I'm your old lover." +
"I'd like to....";
hellRoadPostOffice.sendLetter(context, address);
}
}
複製程式碼
4 優點
- 鬆散耦合:使得客戶端和子系統之間解耦,讓子系統內部的模組功能更容易擴充套件和維護。
- 簡單易用:客戶端根本不需要知道子系統內部的實現,或者根本不需要知道子系統內部的構成,它只需要跟Facade類互動即可。
- 更好的劃分訪問層次:有些方法是對系統外的,有些方法是系統內部相互互動的使用的。子系統把那些暴露給外部的功能集中到門面中,這樣就可以實現客戶端的使用,很好的隱藏了子系統內部的細節。