設(shè)計(jì)模式系列之「門面模式」

《三國演義》中有曰:劉備、諸葛亮趁曹操赤壁之戰(zhàn)失利,大肆擴(kuò)充地盤,先后占領(lǐng)荊州大部地區(qū),引起東吳孫權(quán)的警惕。為了限制劉備勢(shì)力的發(fā)展,魯肅奉命向劉備討還荊州,但遭到拒絕。東吳大都督周瑜向?qū)O權(quán)獻(xiàn)計(jì):趁劉備的甘夫人病故,用孫權(quán)的妹妹孫仁為誘餌,將劉備“賺到南徐,妻子不能勾得,幽囚在獄中”。 但是,這個(gè)詭計(jì)被諸葛亮一眼識(shí)破。他將計(jì)就計(jì),讓劉備“擇日便去就親”,并派趙云前去保護(hù),并給了趙云三個(gè)錦囊,教趙云“依次而行”。結(jié)果,使東吳“賠了夫人又折兵”。此為諸葛亮的錦囊三妙計(jì)。

一、三妙計(jì)

妙計(jì)一:見喬國老,并把劉備娶親的事情搞得東吳人盡皆知。

妙計(jì)二:用謊言(曹操打荊州)騙泡在溫柔鄉(xiāng)里的劉備回去。

妙計(jì)三:讓孫夫人擺平東吳的追兵,她是孫權(quán)妹妹,東吳將領(lǐng)懼她三分。

二、妙計(jì)的兩種實(shí)施方案

1.把三個(gè)錦囊直接交給劉備,讓劉備根據(jù)情況打開錦囊。

2.把錦囊交給趙云,趙云按照諸葛亮的囑咐,依次按照情況使用錦囊。

三、劉備用妙計(jì)

①妙計(jì)的接口

public interface Strategy {
    //妙計(jì)內(nèi)容
    public void carryOut();
}

②妙計(jì)一

public class StrategyOne implements Strategy {

    @Override
    public void carryOut() {
        System.out.println("見喬國老,并把劉備娶親的事情搞得東吳人盡皆知。");
    }
}

③妙計(jì)二

public class StrategyTwo implements Strategy {

    @Override
    public void carryOut() {
        System.out.println("用謊言(曹操打荊州)騙泡在溫柔鄉(xiāng)里的劉備回去。");
    }
}

④妙計(jì)三

public class StrategyThree implements Strategy {

    @Override
    public void carryOut() {
        System.out.println("讓孫夫人擺平東吳的追兵。");
    }
}

⑤劉備使用妙計(jì)

public class Client {
    public static void main(String[] args) {
        //劉備一行人到達(dá)南徐的時(shí)候,打開第一個(gè)錦囊
        Strategy strategyOne=new StrategyOne();
        strategyOne.carryOut();
        //周瑜和孫權(quán)通過計(jì)謀使劉備沉迷在溫柔鄉(xiāng)無法自拔
        Strategy strategyTwo=new StrategyTwo();
        strategyTwo.carryOut();
        //周瑜看計(jì)謀不行,出兵攔殺劉備
        Strategy strategyThree=new StrategyThree();
        strategyThree.carryOut();
    }
}

輸出的結(jié)果為:

//劉備一行人到達(dá)南徐的時(shí)候,打開第一個(gè)錦囊
見喬國老,并把劉備娶親的事情搞得東吳人盡皆知。

//周瑜和孫權(quán)通過計(jì)謀使劉備沉迷在溫柔鄉(xiāng)無法自拔
用謊言(曹操打荊州)騙泡在溫柔鄉(xiāng)里的劉備回去。

//周瑜看計(jì)謀不行,出兵攔殺劉備
讓孫夫人擺平東吳的追兵。

忽略其他正常因素(諸葛亮不可能把錦囊交給劉備實(shí)施),代碼角度分析這種方案帶來的問題

  • 錦囊使用是有前提的,要根據(jù)每個(gè)階段來使用對(duì)應(yīng)的錦囊,在編寫代碼中要清楚它們的順序,一旦出錯(cuò)就會(huì)造成劉備死翹翹。這在面向?qū)ο蟮木幊讨惺菢O度地不適合,它根本就沒有完成一個(gè)類所具有的單一職責(zé)。

  • 外界訪問直接深入到子系統(tǒng)內(nèi)部,相互之間是一種強(qiáng)耦合關(guān)系,這樣的強(qiáng)依賴是系統(tǒng)設(shè)計(jì)所不能接受的。

  • 子系統(tǒng)的內(nèi)部方法直接暴露給外部調(diào)用,安全性低。

  • 當(dāng)錦囊數(shù)越來越多的時(shí)候,那么Client就需要調(diào)用更多錦囊類來實(shí)現(xiàn),這就會(huì)增加Client的實(shí)現(xiàn)難度,維護(hù)更加困難。

四、趙云協(xié)助用妙計(jì)(門面模式)

諸葛亮能夠想到應(yīng)對(duì)之策,當(dāng)然也會(huì)考慮到讓誰和如何實(shí)施這三個(gè)錦囊才能夠讓劉備順利化險(xiǎn)為夷。綜合上面劉備親自實(shí)施錦囊妙計(jì)帶來的問題,安排趙云保管錦囊并在適當(dāng)?shù)臅r(shí)機(jī)協(xié)助實(shí)施才是上上之策。

1.UML實(shí)現(xiàn)

增加了一個(gè)ZhaoYunFacadee類,負(fù)責(zé)對(duì)錦囊實(shí)施過程進(jìn)行封裝,然后高層模塊只要和它有交互就成。

2.增加的代碼模塊

①趙云充當(dāng)門面

public class ZhaoYunFacade {
    //妙計(jì)一
    private Strategy strategyOne=new StrategyOne();
    //妙計(jì)二
    private Strategy strategyTwo=new StrategyTwo();
    //妙計(jì)三
    private Strategy strategyThree=new StrategyThree();

    //三妙計(jì)統(tǒng)一讓趙云協(xié)助實(shí)施
    public void carryOut(){
        //劉備一行人到達(dá)南徐的時(shí)候,打開第一個(gè)錦囊
        strategyOne.carryOut();
        //周瑜和孫權(quán)通過計(jì)謀使劉備沉迷在溫柔鄉(xiāng)無法自拔
        strategyTwo.carryOut();
        //周瑜看計(jì)謀不行,出兵攔殺劉備
        strategyThree.carryOut();
    }
}

劉備在遇到困難的時(shí)候,只要讓趙云根據(jù)諸葛亮的錦囊進(jìn)行處理,這多簡(jiǎn)單,Client減少了很多工作。

②Client

public class Client {
    public static void main(String[] args) {
        //劉備遇到困難,只要通過趙云按照錦囊實(shí)施,就可化險(xiǎn)為夷
        ZhaoYunFacade zhaoYunFacade=new ZhaoYunFacade();
    zhaoYunFacade.carryOut();;
    }   
}

輸出的結(jié)果為:

//劉備一行人到達(dá)南徐的時(shí)候,打開第一個(gè)錦囊
見喬國老,并把劉備娶親的事情搞得東吳人盡皆知。

//周瑜和孫權(quán)通過計(jì)謀使劉備沉迷在溫柔鄉(xiāng)無法自拔
用謊言(曹操打荊州)騙泡在溫柔鄉(xiāng)里的劉備回去。

//周瑜看計(jì)謀不行,出兵攔殺劉備
讓孫夫人擺平東吳的追兵。

運(yùn)行結(jié)果是相同的。場(chǎng)景類簡(jiǎn)化了很多,只要與ZhaoYunFacade交互就成了,其他的什么都不用管,什么時(shí)候使用錦囊、怎么用都不用管,只要調(diào)用ZhaoYunFacade提供的方法,就可以得到想要的妙計(jì),這種方式不僅簡(jiǎn)單,而且擴(kuò)展性還非常好,同時(shí)不改變子系統(tǒng)對(duì)外暴露的接口、方法,只改變內(nèi)部的處理邏輯,其他兄弟模塊的調(diào)用產(chǎn)生了不同的結(jié)果。

3.兩種方案的程序結(jié)構(gòu)圖

  • 沒有采用門面模式
  • 采用門面模式

總的來說,門面對(duì)象是外界訪問子系統(tǒng)內(nèi)部的唯一通道,不管子系統(tǒng)內(nèi)部是多么雜亂無章。

五、門面模式的介紹

1.門面模式的定義

門面模式(Facade Pattern)也叫做外觀模式。要求一個(gè)子系統(tǒng)的外部與其內(nèi)部的通信必須通過一個(gè)統(tǒng)一的對(duì)象進(jìn)行。門面模式提供一個(gè)高層次的接口,使得子系統(tǒng)更易于使用。

2.中介模式的角色介紹

  • Facade門面角色
    客戶端可以調(diào)用這個(gè)角色的方法。此角色知曉子系統(tǒng)的所有功能和責(zé)任。一般情況下,本角色會(huì)將所有從客戶端發(fā)來的請(qǐng)求委派到相應(yīng)的子系統(tǒng)去,也就說該角色沒有實(shí)際的業(yè)務(wù)邏輯,只是一個(gè)委托類。

  • subsystem子系統(tǒng)角色
    可以同時(shí)有一個(gè)或者多個(gè)子系統(tǒng)。每一個(gè)子系統(tǒng)都不是一個(gè)單獨(dú)的類,而是一個(gè)類的集合。子系統(tǒng)并不知道門面的存在。對(duì)于子系統(tǒng)而言,門面僅僅是另外一個(gè)客戶端而已。

3.門面模式的使用場(chǎng)景

  • 為一個(gè)復(fù)雜的模塊或子系統(tǒng)提供一個(gè)供外界訪問的接口。

  • 為降低個(gè)人代碼質(zhì)量對(duì)整體項(xiàng)目的影響風(fēng)險(xiǎn),只能在指定的子系統(tǒng)中開發(fā),然后再提供門面接口進(jìn)行訪問操作。

  • 子系統(tǒng)相對(duì)獨(dú)立——外界對(duì)子系統(tǒng)的訪問只要黑箱操作即可。

六、門面模式優(yōu)缺點(diǎn)

1.優(yōu)點(diǎn)

減少系統(tǒng)的相互依賴。上面也提到不使用門面模式,外界訪問直接深入到子系統(tǒng)內(nèi)部,相互之間是一種強(qiáng)耦合關(guān)系這樣的強(qiáng)依賴是系統(tǒng)設(shè)計(jì)所不能接受的,門面模式的出現(xiàn)就很好地解決了該問題,所有的依賴都是對(duì)門面對(duì)象的依賴,與子系統(tǒng)無關(guān)。

提高了靈活性。依賴減少了,靈活性自然提高了。不管子系統(tǒng)內(nèi)部如何變化,只要不影響到門面對(duì)象,就沒有什么問題了。

提高安全性。訪問子系統(tǒng)的哪些業(yè)務(wù)就開通哪些邏輯,不需要把子系統(tǒng)的內(nèi)部方法直接暴露給外部調(diào)用。

2.缺點(diǎn)

門面模式最大的缺點(diǎn)就是不符合開閉原則,對(duì)修改關(guān)閉,對(duì)擴(kuò)展開放。系統(tǒng)投產(chǎn)后發(fā)現(xiàn)問題唯一能做的一件事就是修改門面角色的代碼,這個(gè)風(fēng)險(xiǎn)相當(dāng)大。

七、簡(jiǎn)單對(duì)比門面模式和中介模式的區(qū)別

1.從定義上,門面模式為復(fù)雜的子系統(tǒng)提供一個(gè)統(tǒng)一的訪問界面,它定義的是一個(gè)高層接口,該接口使得子系統(tǒng)更加容易使用,避免外部模塊深入到子系統(tǒng)內(nèi)部而產(chǎn)生與子系統(tǒng)內(nèi)部細(xì)節(jié)耦合的問題。中介者模式使用一個(gè)中介對(duì)象來封裝一系列同事對(duì)象的交互行為,它使各對(duì)象之間不再顯式地引用,從而使其耦合松散,建立一個(gè)可擴(kuò)展的應(yīng)用架構(gòu)。

2.從功能上,門面模式只是增加了一個(gè)門面,它對(duì)子系統(tǒng)來說沒有增加任何的功能,子系統(tǒng)若脫離門面模式是完全可以獨(dú)立運(yùn)行的。而中介者模式則增加了業(yè)務(wù)功能,它把各個(gè)同事類中的原有耦合關(guān)系移植到了中介者,同事類不可能脫離中介者而獨(dú)立存在。

3.從關(guān)系上,對(duì)門面模式來說,子系統(tǒng)不知道有門面存在,而對(duì)中介者來說,每個(gè)同事類都知道中介者存在,因?yàn)橐揽恐薪檎哒{(diào)和同事之間的關(guān)系,它們對(duì)中介者非常了解。

4.從封裝程度上,門面模式是一種簡(jiǎn)單的封裝,所有的請(qǐng)求處理都委托給子系統(tǒng)完成,而中介者模式則需要有一個(gè)中心,由中心協(xié)調(diào)同事類完成,并且中心本身也完成部分業(yè)務(wù),它屬于更進(jìn)一步的業(yè)務(wù)功能封裝。

八、總結(jié)

門面模式是一個(gè)很好的封裝方法,一個(gè)子系統(tǒng)比較復(fù)雜時(shí),比如算法或者業(yè)務(wù)比較復(fù)雜,就可以封裝出一個(gè)或多個(gè)門面出來,項(xiàng)目的結(jié)構(gòu)簡(jiǎn)單,而且擴(kuò)展性非常好。還有,對(duì)于一個(gè)較大項(xiàng)目,為了避免人員帶來的風(fēng)險(xiǎn),也可以使用門面模式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,491評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,708評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,409評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,939評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,774評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評(píng)論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,650評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容

  • 第一回 宴桃園豪杰三結(jié)義 斬黃巾英雄首立功 漢末十常侍為奸,朝政日非,人心思亂. 張角兄弟起事.百姓擁護(hù),官軍望風(fēng)...
    JACKNPC閱讀 38,065評(píng)論 2 12
  • 首先聲明:我真的不是一個(gè)標(biāo)題黨。這個(gè)標(biāo)題和今天要講的常勝將軍趙云趙子龍絕對(duì)是有關(guān)的,且聽我慢慢八卦。。。。。...
    天外非仙閱讀 2,001評(píng)論 5 12
  • 設(shè)計(jì)模式匯總 一、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 3,957評(píng)論 1 15
  • 文/十月云 (一) 2004年春,一天早上剛上班,S醫(yī)院導(dǎo)診護(hù)士在大廳看到一對(duì)年輕夫婦帶著一個(gè)4、5歲大的男孩,正...
    十月云閱讀 1,531評(píng)論 12 48
  • 《成長(zhǎng)心連心》引用體驗(yàn)式學(xué)習(xí)方法使學(xué)生、家長(zhǎng)、老師體驗(yàn)到全面的教育發(fā)展,不單能夠激發(fā)學(xué)生的內(nèi)在潛力,同時(shí)亦可創(chuàng)...
    潘饒平閱讀 186評(píng)論 0 0