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

《三國(guó)演義》中有曰:劉備、諸葛亮趁曹操赤壁之戰(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ì)一:見(jiàn)喬國(guó)老,并把劉備娶親的事情搞得東吳人盡皆知。

妙計(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("見(jiàn)喬國(guó)老,并把劉備娶親的事情搞得東吳人盡皆知。");
    }
}

③妙計(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)通過(guò)計(jì)謀使劉備沉迷在溫柔鄉(xiāng)無(wú)法自拔
        Strategy strategyTwo=new StrategyTwo();
        strategyTwo.carryOut();
        //周瑜看計(jì)謀不行,出兵攔殺劉備
        Strategy strategyThree=new StrategyThree();
        strategyThree.carryOut();
    }
}

輸出的結(jié)果為:

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

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

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

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

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

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

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

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

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

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

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

增加了一個(gè)ZhaoYunFacadee類,負(fù)責(zé)對(duì)錦囊實(shí)施過(guò)程進(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)通過(guò)計(jì)謀使劉備沉迷在溫柔鄉(xiāng)無(wú)法自拔
        strategyTwo.carryOut();
        //周瑜看計(jì)謀不行,出兵攔殺劉備
        strategyThree.carryOut();
    }
}

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

②Client

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

輸出的結(jié)果為:

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

//周瑜和孫權(quán)通過(guò)計(jì)謀使劉備沉迷在溫柔鄉(xiāng)無(wú)法自拔
用謊言(曹操打荊州)騙泡在溫柔鄉(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)圖

  • 沒(méi)有采用門面模式
  • 采用門面模式

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

五、門面模式的介紹

1.門面模式的定義

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

2.中介模式的角色介紹

  • 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è)客戶端而已。

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

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

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

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

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

1.優(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ì)象,就沒(méi)有什么問(wèn)題了。

提高安全性。訪問(wèn)子系統(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)問(wèn)題唯一能做的一件事就是修改門面角色的代碼,這個(gè)風(fēng)險(xiǎn)相當(dāng)大。

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

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

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

3.從關(guān)系上,對(duì)門面模式來(lái)說(shuō),子系統(tǒng)不知道有門面存在,而對(duì)中介者來(lái)說(shuō),每個(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è)門面出來(lái),項(xiàng)目的結(jié)構(gòu)簡(jiǎn)單,而且擴(kuò)展性非常好。還有,對(duì)于一個(gè)較大項(xiàng)目,為了避免人員帶來(lái)的風(fēng)險(xiǎn),也可以使用門面模式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容