場(chǎng)景分析
- 介紹一種場(chǎng)景宇挫,紅燒魚(yú)
- 假定紅燒魚(yú)包括:腌魚(yú)苛吱,放入姜蒜、辣椒器瘪,煎魚(yú)四個(gè)步驟翠储,對(duì)應(yīng)的類實(shí)體包括Fish, Ginger, Pepper, client 執(zhí)行制作紅燒魚(yú)的動(dòng)作時(shí),可以單獨(dú)一個(gè)一個(gè)調(diào)用橡疼,但如果包括十幾個(gè)步驟時(shí)援所,直接讓Client接觸十幾個(gè)類是比較粗暴的,可以在 Client 和 功能實(shí)體類之間欣除,添加一層封裝類-Facade住拭,facade 將以功能單位進(jìn)行封裝劃分,定義出包含若干環(huán)節(jié)的接口,如將紅燒魚(yú)的所有環(huán)節(jié)封裝到fryFish 接口中
- 病人看病的案例滔岳,Client 即病人杠娱,需要與 掛號(hào)、門診谱煤、取藥摊求、化驗(yàn)等直接打交道,亂刘离、復(fù)雜室叉,若出現(xiàn)一個(gè) 接待人員 facade 代替病人與各個(gè)系統(tǒng)打交道,則會(huì)減輕Client的復(fù)雜性
- java的三層開(kāi)發(fā)模式
角色定義
- 門面角色
- 客戶端直接調(diào)用這個(gè)門面的方法硫惕,門面方法知曉子系統(tǒng)的功能和責(zé)任茧痕,且會(huì)將Client的請(qǐng)求委派到相應(yīng)子系統(tǒng)中
- 子系統(tǒng)角色
- 可以同時(shí)有一個(gè)或多個(gè)子系統(tǒng),每個(gè)子系統(tǒng)都可以直接被Client 調(diào)用恼除,也可被門面調(diào)用
- 對(duì)于子系統(tǒng)而言踪旷,它并不知曉門面的存在,門面于它來(lái)講豁辉,只是另一個(gè)Client而已
代碼展示
- Fish
public class Fish {
//把魚(yú)腌一下
public void pickleFish() {
System.out.println("腌魚(yú)");
}
//煎魚(yú)
public void fryFish() {
System.out.println("煎魚(yú)");
}
}
- Ginger
/**
* 姜
*/
public class Ginger {
//放入姜片
public void fryGinger(){
System.out.println("熱油放入姜片");
}
}
- pepper
/**
* 辣椒
*/
public class Pepper {
//放入辣椒
public void fryPepper() {
System.out.println("炒辣椒");
}
}
- 定義 facade
/**
* 定義紅燒魚(yú)的facade
*/
public class FishFacade {
//把材料準(zhǔn)備好:魚(yú)埃脏,辣椒,姜片
private Fish fish;
private Ginger ginger;
private Pepper pepper;
//準(zhǔn)備材料
public FishFacade() {
//定義材料
fish = new Fish();
ginger = new Ginger();
pepper = new Pepper();
}
//紅燒魚(yú)有若干步驟的秋忙,這里將所有分散步驟統(tǒng)一
//該方法即所謂的 facade,以煎魚(yú)為整體功能模塊构舟,封裝了很多繁雜的環(huán)節(jié)灰追,避免Client 直接各自調(diào)用
//這里我們只是定義菜料,有可能中間還要讓老婆幫忙系下圍裙狗超,或者讓兒子買包鹽去呢
//總之是很多繁雜的邏輯
public void fryFish() {
//先把魚(yú)腌一下
fish.pickleFish();
//放入辣椒
pepper.fryPepper();
//放入姜片
ginger.fryGinger();
//煎魚(yú)
fish.fryFish();
}
}
- 定義 Demo
public class FacadeDemo {
public static void main(String[] args) {
FishFacade fishFacade = new FishFacade();
//調(diào)用 facade
fishFacade.fryFish();
//如果不使用 facade 則 單步執(zhí)行
//腌魚(yú)
//fish.pickleFish();
//油放姜片
//ginger.fryGinger();
//油放辣椒
//pepper.fryPepper();
//煎魚(yú)
//fish.fryFish();
}
}
優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn)
- 對(duì) Client 屏蔽了子系統(tǒng)的復(fù)雜性弹澎,降低了Client 與 子系統(tǒng)的直接交互
- 實(shí)現(xiàn)子系統(tǒng)與 Client 的松耦合,使得子系統(tǒng)的變化不會(huì)影響到Client努咐,只需更改 facade 類即可
- 降低了大型軟件系統(tǒng)的編譯依賴性苦蒿,簡(jiǎn)化了系統(tǒng)在不同平臺(tái)之間的移植過(guò)程 ?渗稍?佩迟?
- 只是提供了一個(gè)訪問(wèn)子系統(tǒng)的統(tǒng)一入口,并不影響用戶直接使用子系統(tǒng)
- 缺點(diǎn)
- 不能很好的限制Client對(duì)子系統(tǒng)的使用(Client可以直接調(diào)用子系統(tǒng))
- 在不引入抽象外觀類的情況下竿屹,增加新的子系統(tǒng)可能需要修改外觀類和客戶端代碼报强,違背開(kāi)閉原則
其他注意點(diǎn)
- 一個(gè)系統(tǒng)可以有多個(gè)外觀類
- 通常只需要一個(gè)外觀類,且此外觀類只有一個(gè)實(shí)例拱燃,即單例類秉溉,可以節(jié)省資源
- 系統(tǒng)可以設(shè)計(jì)多個(gè)外觀類,每個(gè)外觀類都負(fù)責(zé)和一些特定的子系統(tǒng)交互,向用戶提供相應(yīng)的業(yè)務(wù)功能
- 不要試圖通過(guò)外觀類為子系統(tǒng)增加新的行為
- 不要通過(guò)繼承一個(gè)外觀類在子系統(tǒng)中加入新行為召嘶,外觀的用意是為子系統(tǒng)提供一個(gè)集中化和簡(jiǎn)化的溝通渠道父晶,而非向子系統(tǒng)加入新行為,新行為的增加應(yīng)該通過(guò)修改原有子系統(tǒng)或增加新的子系統(tǒng)實(shí)現(xiàn)
- 外觀模式與迪米特法則
- 外觀類充當(dāng)了 Client 和 子系統(tǒng)之間的第三者弄跌,降低了Client 和 子系統(tǒng)的耦合
- 抽象外觀類的引入
- 外觀類缺點(diǎn)違背了開(kāi)閉原則甲喝,當(dāng)增加新的系統(tǒng)或者移出子系統(tǒng)時(shí)需要修改外觀類,可以通過(guò)引入抽象外觀類解決一定的問(wèn)題碟绑,對(duì)于新的業(yè)務(wù)需求俺猿,不修改原有外觀類,而對(duì)應(yīng)增加一個(gè)新的具體外觀類格仲,由新的具體外觀類關(guān)聯(lián)新的子系統(tǒng)對(duì)象
參考:http://blog.csdn.net/xingjiarong/article/details/50066133