《Head First 設(shè)計(jì)模式》《設(shè)計(jì)模式之禪(第二版)》 學(xué)習(xí)筆記,碼云同步更新中
如有錯誤或不足之處野舶,請一定指出岭参,謝謝~
目錄
設(shè)計(jì)原則
- “依賴倒置”原則
- 未完待續(xù)...
設(shè)計(jì)模式
- 設(shè)計(jì)模式——策略模式
- 設(shè)計(jì)模式——裝飾者模式
- 設(shè)計(jì)模式——觀察者模式
- 設(shè)計(jì)模式——簡單工廠
- 設(shè)計(jì)模式——工廠方法模式
- 設(shè)計(jì)模式——抽象工廠模式
- 設(shè)計(jì)模式——單例模式
- 設(shè)計(jì)模式——命令模式
- 設(shè)計(jì)模式——適配器模式
- 設(shè)計(jì)模式——門面模式(外觀模式)
- 未完待續(xù)...
門面模式(外觀模式)(Facade Pattern)
定義
- 要求一個子系統(tǒng)的外部與其內(nèi)部的通信必須通過一個統(tǒng)一的對象進(jìn)行。 門面模式提供一個高層次的接口憨琳, 使得子系統(tǒng)更易于使用物咳。
結(jié)構(gòu)
- Facade:門面(外觀)角色锣险,將收到的請求委派給相應(yīng)的子系統(tǒng)
- Subsystem:子系統(tǒng)角色蹄皱,處理請求,并不知道門面的存在芯肤,只是一個正常的客戶端
優(yōu)點(diǎn)
- 減少系統(tǒng)的相互依賴
- 提高靈活性巷折。無論子系統(tǒng)內(nèi)部如何變化,只需要修改門面一個對象就可以
- 提供安全性崖咨。子系統(tǒng)只能被門面對象訪問
缺點(diǎn)
不符合“開閉原則”锻拘。門面對象有可能會被修改,有一定的風(fēng)險性击蹲。
使用場景
- 為一個復(fù)雜的子系統(tǒng)向外界提供一個簡單明了的訪問接口
- 保持子系統(tǒng)的獨(dú)立性
- 降低因個人代碼質(zhì)量差而對整體質(zhì)量的影響署拟,“畫地為牢”,規(guī)定只能在指定子系統(tǒng)中開發(fā)歌豺,然后對外提供訪問接口
示例
現(xiàn)在來模擬一個寫信推穷、寄信的過程,步驟如下:
/**
* 寫信寄信流程
*/
public class LetterWriter {
/**
* 寫內(nèi)容
*/
public void writeContext(String context) {
System.out.println(context);
}
/**
* 寫信封
*/
public void writeAddress(String address) {
System.out.println(address);
}
/**
* 裝進(jìn)信封
*/
public void putIntoEnvelope() {
System.out.println("mua~");
}
/**
* 投遞
*/
public void sendLetter() {
System.out.println("send the letter...");
}
}
來模擬這個過程:
public class Test {
public static void main(String[] args) {
LoveLetter loveLetter = new LoveLetter();
loveLetter.writeContext("loving u...");
loveLetter.writeAddress("To my lover...");
loveLetter.putIntoEnvelope();
loveLetter.sendLetter();
}
}
我們發(fā)現(xiàn)类咧,寫信的過程很復(fù)雜馒铃,步驟順序不能亂,也不能漏掉痕惋,這還是只有4個步驟的情況区宇。
讓我們用門面模式來改造一下:引入一個郵局類,我們只需要告訴他內(nèi)容和地址值戳,他會幫我們完成整個過程议谷。
public class PostOffice {
private LetterWriter letterWriter = new LetterWriter();
public void sendLetter(String context, String address) {
letterWriter.writeContext(context);
letterWriter.writeAddress(address);
letterWriter.putIntoEnvelope();
letterWriter.sendLetter();
}
}
這時我們寫信就會變得很簡單:
public class Test {
public static void main(String[] args) {
PostOffice postOffice = new PostOffice();
postOffice.sendLetter("love u", "xxx");
}
}
這樣帶來的一個好處就是,簡化客戶端的操作述寡。至于你郵局到底做了什么柿隙,我不關(guān)心,也沒必要關(guān)心鲫凶。信送到了就行禀崖。比如有一天突然多了一個步驟:警察需要檢查信件內(nèi)容。我們只需要修改門面:
public class PostOffice {
private LetterWriter letterWriter = new LetterWriter();
private Police police = new Police();
public void sendLetter(String context, String address) {
letterWriter.writeContext(context);
letterWriter.writeAddress(address);
// 增加警察檢查內(nèi)容步驟
police.checkLetter(letterWriter);
letterWriter.putIntoEnvelope();
letterWriter.sendLetter();
}
}
到這里還沒完螟炫,細(xì)心的朋友們可能已經(jīng)發(fā)現(xiàn)了波附,門面類參與了子系統(tǒng)的業(yè)務(wù)邏輯,這是我們非常不希望看到的昼钻,而且違反了單一職責(zé)原則掸屡。門面應(yīng)該只提供訪問子系統(tǒng)的路徑。我們再來封裝一下然评,在子系統(tǒng)中再封裝一下
/**
* 寄信流程
*/
public class LetterProcess {
private LetterWriter letterWriter = new LetterWriter();
private Police police = new Police();
public void sendLetter(String context, String address) {
letterWriter.writeContext(context);
letterWriter.writeAddress(address);
police.checkLetter(letterWriter);
letterWriter.putIntoEnvelope();
letterWriter.sendLetter();
}
}
然后修改門面:
public class PostOffice {
private LetterProcess letterProcess = new LetterProcess();
public void sendLetter(String context, String address) {
letterProcess.sendLetter(context, address);
}
}
ok仅财,大功告成。
注意事項(xiàng)
- 一個子系統(tǒng)可以有多個門面碗淌,例如:
- 門面已經(jīng)非常龐大盏求,可以按功能分類拆分(增刪改查)
- 多個高層系統(tǒng)訪問門面抖锥,權(quán)限不同,可訪問的方法不同碎罚,根據(jù)權(quán)限創(chuàng)建不同的門面
- 門面不參與子系統(tǒng)業(yè)務(wù)邏輯
- 子系統(tǒng)的業(yè)務(wù)邏輯是會經(jīng)常變動的磅废,但門面在系統(tǒng)投入使用后應(yīng)該保持穩(wěn)定。 子系統(tǒng)不應(yīng)該依賴門面才能被訪問荆烈。
門面模式 vs 適配器模式
門面模式其實(shí)和上一節(jié)的適配器模式非常非常相似拯勉,他們都封裝了(來自一個類或多個類的)一組接口,讓客戶與子系統(tǒng)解耦憔购。但他們的意圖完全不同:
* 適配器模式:將一組接口轉(zhuǎn)化為另一組不同的接口
* 門面模式:簡化接口