門面模式本質(zhì)上就是化零為整稍途;引入一個中介類着逐,把各個分散的功能組合成一個整體,只對外暴露一個統(tǒng)一的接口漆际。
門面模式實現(xiàn)簡單的解耦淆珊,也可以實現(xiàn)功能模塊化。
1. 概念
提供一個統(tǒng)一的接口去訪問多個子系統(tǒng)的多個不同的接口奸汇,它為子系統(tǒng)中的一組接口提供了一個統(tǒng)一的高層接口施符。使用子系統(tǒng)更容易使用。
2. 目的
為了用戶使用方便擂找,把過度拆分的分散功能戳吝,組合成一個整體,對外提供一個統(tǒng)一的接口贯涎。
3. 解決方案
本質(zhì):引入一個第三方中介類听哭,這個類集合了多個零部件類的功能,實際功能則委托給這些零部件對象,這個類只是做為對外統(tǒng)一接口陆盘,只是一個馬甲普筹。
4. 門面模式的結(jié)構(gòu)
4.1 門面角色的類圖
所有實現(xiàn)類的地方都可以面向抽象編程(增加接口)
在這個對象圖中,出現(xiàn)了兩個角色:
-
門面(Facade
[f??sɑ:d]
)角色:客戶端可以調(diào)用這個角色的方法隘马,此角色知曉相關(guān)的(一個或者多個)子系統(tǒng)的功能和責(zé)任太防。在正常情況下,本角色會將所有從客戶端發(fā)來的請求委托到相應(yīng)的子系統(tǒng)去祟霍。 - 子系統(tǒng)(SubSystem)角色:可以同時又一個或者多個子系統(tǒng)杏头。每個子系統(tǒng)都不是一個單獨的類,而是一個類的集合(如上面的子系統(tǒng)SubsystemA沸呐、SubsystemB醇王、SubsystemN等組合而成)。每個子系統(tǒng)都可以被客戶端直接調(diào)用崭添,或者被門面角色調(diào)用寓娩。子系統(tǒng)不知道門面的存在,對于子系統(tǒng)來說呼渣,門面僅僅是另外一個客戶端而已棘伴。
4.2 門面角色簡單的源代碼
1. 子系統(tǒng)角色類
public class SubSystemA {
//子模塊方法A
public void testA() {
System.out.println(String.format("調(diào)用了%s模塊的%s方法", "SubSystemA", "testA"));
}
}
public class SubSystemB {
//子模塊方法B
public void testB() {
System.out.println(String.format("調(diào)用了%s模塊的%s方法", "SubSystemB", "testB"));
}
}
public class SubSystemN {
//子模塊方法N
public void testN() {
System.out.println(String.format("調(diào)用了%s模塊的%s方法", "SubSystemN", "testN"));
}
}
2. 門面角色類
//門面角色類
public class Facade {
//示意方法,滿足客戶端需求
private SubSystemA subSystemA=new SubSystemA();
private SubSystemB subSystemB=new SubSystemB();
private SubSystemN subSystemN=new SubSystemN();
//門面提供給客戶端的方法
public void methodA(){
subSystemA.testA();
}
public void methodB(){
subSystemB.testB();
}
public void methodC() {
subSystemN.testN();
}
}
3. 客戶端類
//客戶端角色類
public class Client {
public static void main(String[] args) {
Facade facade=new Facade();
facade.methodB();
}
}
Facade類相當(dāng)于A屁置、B焊夸、C模塊的外觀界面,有了這個Facade類蓝角,那么客戶端就不需要親自調(diào)用子系統(tǒng)中的A阱穗、B、C模塊了使鹅,也不需要知道系統(tǒng)內(nèi)部實現(xiàn)的細(xì)節(jié)揪阶,甚至不需要知道A、B患朱、C模塊的存在鲁僚,客戶端就只需跟Facade類交互就好了,從而更好地實現(xiàn)了客戶端和子系統(tǒng)中A裁厅、B冰沙、C模塊的解耦,讓客戶端更容易地使用系統(tǒng)执虹。
4.3門面模式的實現(xiàn)
使用門面模式還有一個附帶的好處倦淀,就是能夠有選擇性地的暴露方法。一個模塊中定義的方法可以分成兩部分声畏,一部分是給子系統(tǒng)外部使用的,一部分是子系統(tǒng)內(nèi)部模塊之間相互調(diào)用的。有了Facade類插龄,那么子系統(tǒng)內(nèi)部模塊之間相互調(diào)用的方法就不用暴露給子系統(tǒng)外部了愿棋。
這樣定義一個ModuleFacade類可以有效地屏蔽內(nèi)部的細(xì)節(jié),免得客戶端去調(diào)用Module類時均牢,發(fā)現(xiàn)一些不需要它知道的方法糠雨。比如a2()和a3()方法就不需要讓客戶端知道,否則既暴露了內(nèi)部的細(xì)節(jié)徘跪,又讓客戶端迷惑甘邀。對客戶端來說,他可能還要去思考a2()垮庐、a3()方法用來干什么呢松邪?其實a2()和a3()方法是內(nèi)部模塊之間交互的,原本就不是對子系統(tǒng)外部的哨查,所以干脆就不要讓客戶端知道逗抑。
4.4 一個系統(tǒng)可以有幾個門面類
在門面模式中寒亥,通常只需要一個門面類,并且此門面類只有一個實例溉奕,換言之它是一個單例類。當(dāng)然這并不意味著在整個系統(tǒng)里只有一個門面類加勤,而僅僅是說對每一個子系統(tǒng)只有一個門面類仙辟。或者說胸竞,如果一個系統(tǒng)有好幾個子系統(tǒng)的話,每一個子系統(tǒng)都有一個門面類卫枝,整個系統(tǒng)可以有數(shù)個門面類。
4.5 為子系統(tǒng)增加新行為
初學(xué)者往往以為通過繼承一個門面類便可在子系統(tǒng)中加入新的行為校赤,這是錯誤的吆玖。門面模式的用意是為子系統(tǒng)提供一個集中化和簡化的溝通管道,而不能向子系統(tǒng)加入新的行為马篮。比如醫(yī)院中的接待員并不是醫(yī)護人員沾乘,接待員并不能為病人提供醫(yī)療服務(wù)浑测。
5. 優(yōu)缺點
5.1 優(yōu)點
- 松耦合
用戶與子系統(tǒng)解耦歪玲,屏蔽子系統(tǒng)掷匠;可以提高子系統(tǒng)的獨立性; - 使用簡單
簡化用戶與子系統(tǒng)的依賴關(guān)系讹语;
用戶只與門面對接,有統(tǒng)一的入口顽决;不需要知道所有子系統(tǒng)及內(nèi)部構(gòu)造; - 提高安全性
想讓你訪問子系統(tǒng)就開通哪些邏輯茸时,不在門面上開通的方法,客戶端就訪問不到屹蚊。
5.2 缺點
- 不規(guī)范的編程方式
沒有面向抽象編程进每,而是通過增加中介層,轉(zhuǎn)換服務(wù)提供方的服務(wù)接口田晚;
2. 門面模式最大的缺點就是不符合開閉原則。
最核心的目的:簡化子系統(tǒng)贤徒,簡化客戶使用,屏蔽多個子系統(tǒng)踢涌。
6. 應(yīng)用場景
- 簡化子系統(tǒng)復(fù)雜性序宦;
- 監(jiān)控所有子系統(tǒng)時;通過門面控制入口互捌,可以統(tǒng)一監(jiān)控;
- 希望封裝和隱藏子系統(tǒng)時钳降;
- 兩歷史系統(tǒng)進(jìn)行改造并打通關(guān)系時;