一:門面模式的定義
外觀模式的目的不是給予子系統(tǒng)添加新的功能接口您朽,而是為了讓外部減少與子系統(tǒng)內(nèi)多個(gè)模塊的交互,松散耦合,從而讓外部能夠更簡(jiǎn)單地使用子系統(tǒng)。
外觀模式的本質(zhì)是:封裝交互粒没,簡(jiǎn)化調(diào)用。
外觀模式的一般描述是:外觀模式定義了一個(gè)高層的功能簇爆,為子系統(tǒng)中的多個(gè)模塊協(xié)同的完成某種功能需求提供簡(jiǎn)單的對(duì)外功能調(diào)用方式癞松,使得這一子系統(tǒng)更加容易被外部使用爽撒。
--->門面模式(Facade Pattern)也叫做外觀模式,是一種比較常用的封裝模式
--->要求一個(gè)子系統(tǒng)的外部與其內(nèi)部的通信必須通過(guò)一個(gè)統(tǒng)一的對(duì)象進(jìn)行。門面模式提供一個(gè)高層次的接口,使得子系統(tǒng)更易于使用响蓉。
--->門面模式注重“統(tǒng)一的對(duì)象”,也就是提供一個(gè)訪問(wèn)子系統(tǒng)的接口,除了這個(gè)接口不允許有任何訪問(wèn)子系統(tǒng)的行為發(fā)生
--->這正是我們?cè)O(shè)計(jì)所需要的模式,不改變子系統(tǒng)對(duì)外暴露的接口硕勿、方法,只改變內(nèi)部的處理邏輯,其他兄弟模塊的調(diào)用產(chǎn)生了不同的結(jié)果,確實(shí)是一個(gè)非常棒的設(shè)計(jì)。這就是門面模式
二:門面模式的角色
● Facade門面角色
客戶端可以調(diào)用這個(gè)角色的方法厕妖。此角色知曉子系統(tǒng)的所有功能和責(zé)任首尼。一般情況下,本角色會(huì)將所有從客戶端發(fā)來(lái)的請(qǐng)求委派到相應(yīng)的子系統(tǒng)去,也就說(shuō)該角色沒(méi)有實(shí)際的業(yè)務(wù)邏輯,只是一個(gè)委托類挑庶。
● subsystem子系統(tǒng)角色
可以同時(shí)有一個(gè)或者多個(gè)子系統(tǒng)言秸。每一個(gè)子系統(tǒng)都不是一個(gè)單獨(dú)的類,而是一個(gè)類的集合。子系統(tǒng)并不知道門面的存在迎捺。對(duì)于子系統(tǒng)而言,門面僅僅是另外一個(gè)客戶端而已举畸。
三:門面模式的應(yīng)用
門面模式有如下優(yōu)點(diǎn)
● 減少系統(tǒng)的相互依賴
想想看,如果我們不使用門面模式,外界訪問(wèn)直接深入到子系統(tǒng)內(nèi)部,相互之間是一種強(qiáng)耦合關(guān)系,你死我就死,你活我才能活,這樣的強(qiáng)依賴是系統(tǒng)設(shè)計(jì)所不能接受的,門面模式的出現(xiàn)就很好地解決了該問(wèn)題,所有的依賴都是對(duì)門面對(duì)象的依賴,與子系統(tǒng)無(wú)關(guān)。
● 提高了靈活性
依賴減少了,靈活性自然提高了凳枝。不管子系統(tǒng)內(nèi)部如何變化,只要不影響到門面對(duì)象,任你自由活動(dòng)抄沮。
● 提高安全性
想讓你訪問(wèn)子系統(tǒng)的哪些業(yè)務(wù)就開(kāi)通哪些邏輯,不在門面上開(kāi)通的方法,你休想訪問(wèn)到。
門面模式有如下缺點(diǎn)
●門面模式最大的缺點(diǎn)就是不符合開(kāi)閉原則,對(duì)修改關(guān)閉,對(duì)擴(kuò)展開(kāi)放,看看我們那個(gè)門對(duì)象吧,它可是重中之重,一旦在系統(tǒng)投產(chǎn)后發(fā)現(xiàn)有一個(gè)小錯(cuò)誤,你怎么解決?完全遵從開(kāi)閉原則,根本沒(méi)辦法解決岖瑰。繼承?覆寫?都頂不上用,唯一能做的一件事就是修改門面角色的代碼,這個(gè)風(fēng)險(xiǎn)相當(dāng)大,這就需要大家在設(shè)計(jì)的時(shí)候慎之又慎,多思考幾遍才會(huì)有好收獲叛买。
門面模式的使用場(chǎng)景
● 為一個(gè)復(fù)雜的模塊或子系統(tǒng)提供一個(gè)供外界訪問(wèn)的接口
● 子系統(tǒng)相對(duì)獨(dú)立——外界對(duì)子系統(tǒng)的訪問(wèn)只要黑箱操作即可
比如利息的計(jì)算問(wèn)題,沒(méi)有深厚的業(yè)務(wù)知識(shí)和扎實(shí)的技術(shù)水平是不可能開(kāi)發(fā)出該子系統(tǒng)的,但是對(duì)于使用該系統(tǒng)的開(kāi)發(fā)人員來(lái)說(shuō),他需要做的就是輸入金額以及存期,其他的都不用關(guān)心,返回的結(jié)果就是利息,這時(shí)候,門面模式是非使用不可了。
● 預(yù)防低水平人員帶來(lái)的風(fēng)險(xiǎn)擴(kuò)散
比如一個(gè)低水平的技術(shù)人員參與項(xiàng)目開(kāi)發(fā),為降低個(gè)人代碼質(zhì)量對(duì)整體項(xiàng)目的影響風(fēng)險(xiǎn),一般的做法是“畫地為牢”,只能在指定的子系統(tǒng)中開(kāi)發(fā),然后再提供門面接口進(jìn)行訪問(wèn)操作蹋订。
四:門面模式的注意事項(xiàng)
---> 一個(gè)子系統(tǒng)可以有多個(gè)門面
● 門面已經(jīng)龐大到不能忍受的程度
比如一個(gè)純潔的門面對(duì)象已經(jīng)超過(guò)了200行的代碼,雖然都是非常簡(jiǎn)單的委托操作,也建議拆分成多個(gè)門面,否則會(huì)給以后的維護(hù)和擴(kuò)展帶來(lái)不必要的麻煩率挣。那怎么拆分呢?按照功能拆分是一個(gè)非常好的原則,比如一個(gè)數(shù)據(jù)庫(kù)操作的門面可以拆分為查詢門面、刪除門面露戒、更新門面等椒功。
● 子系統(tǒng)可以提供不同訪問(wèn)路徑
如果A角色,B角色外部系統(tǒng)訪問(wèn)門面C智什,A角色有權(quán)限訪問(wèn)門面C所有的方法动漾,但B角色只有訪問(wèn)門面C一部分方法。則需要新建立一個(gè)門面D供B角色使用荠锭,而D門面只是代理了門面A旱眯,A門面給D門面提供B角色的權(quán)限。
--->門面不參與子系統(tǒng)內(nèi)的業(yè)務(wù)邏輯
門面不參與子系統(tǒng)內(nèi)的業(yè)務(wù)邏輯 证九,如果門面內(nèi)依賴的角色有相互調(diào)用的關(guān)系删豺,則需要將項(xiàng)目調(diào)用的角色封裝成一個(gè)新的角色,聚合到門面中甫贯。
五:門面模式的實(shí)戰(zhàn)
門面模式是一個(gè)很好的封裝方法,一個(gè)子系統(tǒng)比較復(fù)雜時(shí),比如算法或者業(yè)務(wù)比較復(fù)雜,就可以封裝出一個(gè)或多個(gè)門面出來(lái),項(xiàng)目的結(jié)構(gòu)簡(jiǎn)單,而且擴(kuò)展性非常好吼鳞。還有,對(duì)于一個(gè)較大項(xiàng)目,為了避免人員帶來(lái)的風(fēng)險(xiǎn),也可以使用門面模式,技術(shù)水平比較差的成員,盡量安排獨(dú)立的模塊,然后把他寫的程序封裝到一個(gè)門面里
六:門面模式的案例
【1】寫信的業(yè)務(wù)類
package com.yeepay.sxf.template18;
/*** 寫信的業(yè)務(wù)類?隱藏在門面角色里邊,不需要暴露太多*/
public interface? ILetterProcess {//寫信的內(nèi)容
public void writeContext(String context);//寫信的地址
public void fillEnvelope(String address);//將信裝入信封
public void letterInotoEnvelope();//發(fā)送信件
public void sendLetter();}
【2】寫信的業(yè)務(wù)類的實(shí)現(xiàn)
public class LetterProcessImpl? implements ILetterProcess{
@Override
public void writeContext(String context) {System.out.println("LetterProcessImpl.writeContext()寫信的內(nèi)容:"+context);}
@Override
public void fillEnvelope(String address) {System.out.println("LetterProcessImpl.fillEnvelope()寫信的郵寄地址:"+address);}
@Override
public void letterInotoEnvelope() {System.out.println("LetterProcessImpl.letterInotoEnvelope()將信裝入信封");}
@Override
public void sendLetter() {System.out.println("LetterProcessImpl.sendLetter()郵寄信");}
}
【3】寫信的業(yè)務(wù)類的門面角色
package com.yeepay.sxf.template18;
/*** 寫信的門面角色?一個(gè)人想寫信叫搁,只需要給這個(gè)門面提供相應(yīng)的參數(shù)赔桌,后續(xù)事件不用關(guān)心供炎。*/
public class ModenPostOffce {
private ILetterProcess letterProcess;
public ModenPostOffce(ILetterProcess letterProcess){this.letterProcess=letterProcess;}
public void sendLetter(String context,String address){//寫信
letterProcess.writeContext(context);//寫地址
letterProcess.fillEnvelope(address);//裝信封
letterProcess.letterInotoEnvelope();//發(fā)送信件
letterProcess.sendLetter();}}
【4】客戶端測(cè)試
public class ClientTest {
public static void main(String[] args) {//寫信的業(yè)務(wù)類
ILetterProcess letterProcess=new LetterProcessImpl();//寫信業(yè)務(wù)類的門面類
ModenPostOffce modenPostOffce=new ModenPostOffce(letterProcess);//一個(gè)人員通過(guò)門面寫信
modenPostOffce.sendLetter("dddsdfdf", "cccccccccc");}}