我們已經知道介面卡模式是如何將乙個類的介面轉換成另乙個符合客戶期望的介面的。現在我們要看乙個改變介面的新模式,但是它改變介面的原因是為了簡化介面。這個模式被巧妙地命名為外觀模式,之所以這麼稱呼,是因為它將乙個或數個類的複雜的一切都隱藏在背後,只顯露出乙個乾淨美好的外觀。
甜蜜的家庭影院
在我們進入外觀模式的細節之前,讓我們看乙個風行全美的熱潮:建立自己的家庭影院。
你花了好幾個星期佈線、掛上投影機、連線所有的裝置並進行微調。現在,你準備開始享受一部電影……
挑選一部***影片,放鬆,準備開始感受電影的魔幻魅力。哎呀!忘了一件事:想看電影,必須先執行一些任務:
1. 開啟爆公尺花機;
2. 開始爆公尺花;
3. 將燈光調暗;
4. 放下螢幕;
5. 開啟投影機;
6. 將投影機的輸入切換到***;
7. 將投影機設定在寬屏模式;
8. 開啟功放;
9. 將功放的輸入設定為***;
10. 將功放設定為環繞立體聲;
11. 將功放音量調到中;
讓我們將這些任務寫成類和方法的呼叫:
// 開啟爆公尺花機,開始爆公尺花
popper.on();
popper.pop();
// 燈光調到10%的亮度
lights.dim(10);
// 把螢幕放下來
screen.down();
// 開啟投影機,並將它設定在寬屏模式
projector.on();
projector.setinput(***);
projector.widescreenmode();
// 開啟功放,設定為***,調整成環繞立體聲模式,音量調到5
amp.on();
amp.set***(***);
amp.setsurroundsound();
amp.setvolume(5);
// 開啟***機,「終於」可以看電影了!
***.on();
***.play(movies);
但還不只這樣:
看完電影後,你還要把一切都關掉,怎麼辦?難道要反向地把這一切動作再進行一次?
如果要聽cd或者廣播,難道也會這麼麻煩?
如果你決定要公升級你的系統,可能還必須重新學習一套稍微不同的操作過程。
怎麼辦?使用你的家庭影院竟變得如此複雜!讓我們看看外觀模式如何解決這團混亂,好讓你能輕易地享受電影。
構造家庭影院外觀
你需要的正是乙個外觀:有了外觀模式,通過實現乙個提供更合理的介面的外觀類,你可以將乙個複雜的子系統變得容易使用。如果你需要複雜子系統的強大威力,別擔心,還是可以使用原來的複雜介面的;但如果你需要的是乙個方便使用的介面,那就使用外觀。
現在是為家庭影院系統建立乙個外觀的時候了,於是我們了建立乙個名為hometheate***cade的新類,它對外暴露出幾個簡單的方法,例如watchmovie()。
這個外觀類將家庭影院的諸多元件視為乙個系統,通過呼叫這個子系統,來實現watchmovie()方法。
外觀只是提供你更直接的操作,並未將原來的子系統阻隔起來。如果你需要子系統類的更高層功能,還是可以使用原來的子系統。
讓我們逐步構造家庭影院外觀:第一步是使用組合讓外觀能夠訪問子系統中所有的元件。
public class hometheate***cade
}
現在該是時候將子系統的元件整合成乙個統一的介面了。讓我們實現watchmovie()和endmovie()方法。
public void watchmovie(string movie)
public void endmovie()
現在,讓我們用輕鬆的方式去觀賞電影:
hometheate***cade hometheate***cade = new hometheate***cade(amp, tuner, ***, cd, projector, lights, screen, popper);
hometheate***cade.watchmovie("pulp fiction");
hometheate***cade.endmovie();
定義外觀模式
想要使用外觀模式,我們建立了乙個介面簡化而統一的類,用來包裝子系統中乙個或多個複雜的類。外觀模式相當直接,很容易理解,這方面和許多其他的模式不太一樣。但這並不會降低它的威力:外觀模式允許我們讓客戶和子系統之間避免緊耦合。
外觀模式提供了乙個統一的介面,用來訪問子系統中的一群介面。外觀定義了乙個高層介面,讓子系統更容易使用。
現在我們來看乙個新的oo原則:
最少知識原則:只和你的密友談話。
這到底是什麼意思?這是說,當你正在設計乙個系統,不管是任何物件,你都要注意它所互動的類有哪些,並注意它和這些類是如何互動的。
這個原則希望我們在設計中,不要讓太多的類耦合在一起,免得修改系統中一部分,會影響到其他部分。如果許多類之間相互依賴,那麼這個系統會變成乙個易碎的系統,它需要花許多成本維護,也會因為太複雜而不容易被其他人了解。
究竟要怎樣才能避免這樣呢?這個原則提供了一些方針:就任何物件而言,在該物件的方法內,我們只應該呼叫屬於以下範圍的方法:
1. 該物件本身;
2. 被當做方法的引數而傳遞進來的物件;
3. 此方法所建立或例項化的任何物件;
4. 物件的任何元件。
這聽起來有點嚴厲,不是嗎?如果呼叫從另乙個呼叫中返回的物件的方法,會有什麼害處呢?如果我們這樣做,相當於向另乙個物件的子部分發請求(而增加我們直接認識的物件數目)。在這種情況下,原則要我們改為要求該物件為我們做出請求,這麼一來,我們就不需要認識該物件的元件了(讓我們的朋友圈子維持在最小的狀態)。比方說:
// 這裡,我們從氣象站取得了溫度計物件,然後再從溫度計物件取得溫度
public float gettemp()
// 在應用最少知識原則時,我們在氣象站中加進乙個方法,用來向溫度計請求溫度。
// 這可以減少我們所依賴的類的數目
public float gettemp()
設計模式之外觀模式
外觀模式提供了乙個統一的介面,用來訪問子系統中的一群介面。這樣可以避免客戶端和子系統之間的緊耦合。這種模式需要將一系列的子系統組合到外觀中,然後將具體的工作交給各個子系統去完成。如此一來,可以簡化介面的呼叫。其本質就是將系統與客戶端互動的地方封裝起來。這個模式,總體來說,很簡單,理解起來也不困難。依...
設計模式之外觀模式
外觀模式 為子系統中的一組介面提供乙個一直的介面,此模式定義了乙個高層介面,這個介面使得這一子系統更加容易使用。即通過乙個中類來完成客戶端的請求。拿機房收費系統的上機過程來說,上機需要顯示上機者的資訊,填寫上機狀態表,填寫上機記錄表。而使用者不需要知道這些功能是怎麼實現的,只需要通過介面操作就可以完...
設計模式之外觀模式
外觀模式,為子系統中的一組介面提供乙個一致的介面,此模式定義了乙個高層介面,這個介面使得這一子系統更加容易使用。在設計初期階段,應該要有意識的將不同的兩個層分離,比如經典的三層架構,層與層之間建立外觀facade。在開發階段,子系統往往因不斷的重構演化而變得越來越複雜,增加外觀模式可以提供乙個簡單的...