表象模式(Facade Pattern)
我們知道,轉接器模式是透過介面的包裝,讓兩個素不相往來的物件開始友好的一個模式!
最棒的是,這種介面的使用上,他不用修改舊物件的程式碼就可以達到這樣的效益。
其實「表象模式」是另一個,透過改變介面的模式!只是,表象模式想這麼做的理由,是為了要簡化介面。
接著來說說今天的故事。
我愛唱KTV!!
這是真的,平常去好樂x,錢x都唱很久,唱到喉嚨都啞了
不過這次我們準備在家歡唱
不像是好樂x,在我們唱 KTV之前必須做一些準備。
一步一步來吧,唱歌總要有零嘴。所以…
1.打開炸薯條機
2.開始炸薯條
接著是環境的設定
3.放下營幕
4.打開投影機
5.將擴大機打開並調成AUX模式
6.打開音響後級
7.切換投影機成卡拉ok模式
8.打開卡拉OK機
9.切換卡拉OK機成伴唱模式
10.設定麥克風音量為4
11.設定…
2x.開始唱歌
天啊;在家唱KTV就是這麼麻煩,要設定這麼多的開關。
寫成程式來控制的話就像以下:
1: 炸薯條機.On();
2: 炸薯條機.Run();
3:
4: 營幕.Down();
5:
6: 投影機.On();
7: 投影機.SetInput(擴大機);
8:
9: 擴大機.On();
10: 擴大機.SetInput(Aux);
11:
12: 音響後級.On();
13:
14: 卡拉OK機.On();
15: 卡拉OK機.SetSong(11234);
16: 卡拉OK機.SetNoVoiceMode();
17: 卡拉OK機.SetMicVolume(4);
18:
19: 卡拉OK機.Play(); //終於可以開始唱了
上述程式,共牽扯到6個類別,我們一步一步的做完(甚至還有省略一些步驟)。最後終於設定好歌曲、麥克風,可以歡唱了。
3個小時過後…
歡唱完,我們要將一切設備都關掉,怎麼辦呢?反向地將這一切的動作都再進行一次嗎?
未來假如要看dvd的話,或是只是要聽CD,是不是也是這麼的麻煩。
假如未來這套KTV劇院系統升級了,還必須重新設計稍稍不同的流程。
因此當我們自己在家唱ktv,顯然就是要執行這麼的複雜流程。
假如有一套「智慧」系統,自動地幫我們做掉這些呢?
噹噹~~
有一個表象模式你就可以解決這些繁複的流程。
表象模式可以將一個複雜的次系統,變的更加的友善 。
怎麼做呢?
現在我們就為卡拉ok劇院建立一個表象
於是我們建立了一個Home Movie Keraok表象的新類別,僅對外揭露幾個簡單的方法。例如,唱卡拉ok
回頭看看
這個表象類別,將整個卡拉ok系統的諸多元件,視為一個次系統,但是表象模式並非封裝了次系統。
表象提供了簡化的介面操作這些類別,所以客戶那一端如果覺得有必要,依然可以直接使用次系統的類別。
表象模式可以將客戶的程式碼從次系統中鬆綁。例如當初假如是透過表象模式來操作這個卡拉ok,那未來若要從金x換到點將x公司的卡拉ok
或是升級了音響設備,都不須改變客戶的程式碼,而只須改動表象的程式碼。
這樣看起來
轉接器模式與表象模式看起來做的方向一樣,但是這兩個模式的差異在於他們的目的仍是不同。
轉接器模式的目的是改變介面來符合客戶的期望,也就是要介面轉成不同的介面(客戶要的),然而表象模式的目的是提供次系統一個簡化的介面。
1: public class HomeKeraokTheaterFacade
2: {
3: Amplifier amp;
4: DVDPlayer dvd;
5: CDPlayer cd;
6: Projector projector;
7: Screen screen;
8: Light light;
9: Keraok keraok;
10:
11: //建構式
12: public HomeKeraokTheaterFacade(Amplifier amp, DVDPlayer dvd , CDPlayer cd , Projector projector , Screen screen , Light light , Keraok keraok)
13: {
14: this.amp = amp;
15: this.dvd= dvd;
16: this.cd = cd ;
17: this.projector= projector;
18: this.screen= screen;
19: this.light= light;
20: this.keraok= keraok;
21: }
22:
23: //開啟卡拉ok
24: public void TurnOnKeraok(){
25: amp.on;
26: screen.down();
27: projector.on();
28: light.off();
29: keraok.on();
30: keraok.setMicVolume(4);//設定音量
31: keraok.setNoVoice(); //設定伴唱模式
32: }
33:
34: //點歌
35: public void SelectSong(string SongID){
36: keraok.SetSong(SongID);
37: }
38:
39: //關閉卡拉ok系統
40: public void TurnOffKeraok(){
41: amp.off;
42: screen.up();
43: projector.off();
44: light.on();
45: keraok.off();
46: }
47: }
因為我們之後在家唱卡拉ok也可以用輕鬆的方式來實踐了!
HomeKeraokTheaterFacade.TurnOnKeraok();
表象模式將多個類別所造成的一切複雜的真象,隱藏在背後,只顯露出一個美好的介面。
我們定義一下表象模式吧:(以下來自於Head First Design Pattern)
表象模式:提供了一個統一的介面,用來存取次系統中的一群介面。表象定義了一個較高層次的介面,讓次系統更容易使用。
然後 OO守則又多了一條:極小化守則(Least Knowledge),又可叫(Law of Demeter)
極小化守則是說,我們將來在設計系統的時候,不要將一堆類別綑綁在一起,我們要注意類別之間的互動。如果許多類別互相依賴
那就容易是一個易碎的系統。一當需求變動的時候,修改系統的一小部分都會影響到其他的部分。
這個守則另外還告訴我們,若以一個物件而言,此物件的方法定義內, 只應該引用物件的某些方法 這些方法必須屬於:
1.物件本身
2.被當作方法的參數而傳遞進來的物件
3.此方法所建立或實體化的任何物件
4.物件的任何元件。
也就是說,希望我們類別之間要保持朋友圈子為最小的狀態。
例如
1: public int GetSpeed
2: {
3: //不採用這個守則
4: Speeder speeder = car.getSpeeder(); //取得時速表
5: return speeder.getSpeed(); //透過時速表取得時速
6: }
7:
8: public int GetSpeed
9: {
10: //採用這個守則
11: //我們在車子類別加入一個方法,來取得時速
12: //這樣就可以減少所依賴的類別數量
13: return car.getSpeed();
14: }
最後我們回顧一下,表象模式,未來你也可以透過表象模式幫客戶管理自己次系統中的全部元件了