1. 程式人生 > >《Head First 設計模式》:外觀模式

《Head First 設計模式》:外觀模式

# 正文 ## 一、定義 外觀模式提供了一個統一的介面,用來訪問子系統中的一群介面。外觀定義了一個高層介面,讓子系統更容易使用。 **要點:** * 外觀模式將一個或數個類的複雜的一切都隱藏在背後,只顯露出一個乾淨美好的外觀。 * 通過將子系統的方法封裝到外觀的方法中,可以達到對子系統的“一鍵操作”。 * 外觀模式的意圖是簡化介面,好讓一個子系統更易於使用。 * 外觀模式將客戶從元件的子系統中解耦。 ## 二、實現步驟 ### 1、建立子系統元件類 #### (1)子系統元件A ``` /** * 子系統元件A */ public class ComponentA { public void action() { System.out.println("ComponentA action..."); } } ``` #### (2)子系統元件B ``` /** * 子系統元件B */ public class ComponentB { public void action() { System.out.println("ComponentB action..."); } } ``` #### (3)子系統元件C ``` /** * 子系統元件C */ public class ComponentC { public void action() { System.out.println("ComponentC action..."); } } ``` ### 2、建立外觀類 外觀類的方法封裝了子系統元件的一系列方法。這樣,客戶就可以通過外觀類的方法,來一次性呼叫一系列子系統元件的方法。而不是一個個去呼叫子系統元件的方法。 ``` /** * 外觀類 */ public class Facade { ComponentA componentA; ComponentB componentB; ComponentC componentC; public Facade(ComponentA componentA, ComponentB componentB, ComponentC componentC) { this.componentA = componentA; this.componentB = componentB; this.componentC = componentC; } /** * 通過外觀類,請求子系統元件 */ public void request() { componentA.action(); componentB.action(); componentC.action(); } } ``` ### 3、使用外觀訪問子系統元件 ``` public class Test { public static void main(String[] args) { // 子系統元件 ComponentA componentA = new ComponentA(); ComponentB componentB = new ComponentB(); ComponentC componentC = new ComponentC(); // 外觀類 Facade facade = new Facade(componentA, componentB, componentC); facade.request(); } } ``` ## 三、舉個栗子 ### 1、背景 假設你打算建立自己的家庭影院,通過一番研究比較,你組裝了一套殺手級的系統,內含 DVD 播放器、投影機、自動螢幕、環繞立體聲,甚至還有爆米花機。 你花了幾個星期佈線、掛上投影機、連線所有的裝置並進行微調。現在你打算播放一部 DVD 影片放鬆一下。 但是你發現,在看電影前,必須先進行一系列操作:開啟爆米花機 -> 開始爆米花 -> 將燈光調暗 -> 放下螢幕 -> 開啟投影機 -> 將投影機的輸入切換到 DVD -> 將投影機設定在寬屏模式 -> 開啟功放 -> 將功放的輸入設定為 DVD -> 將功放設定為環繞立體聲 -> 將功放音量調到中(5) -> 開啟 DVD 播放器 -> 開始播放 DVD。 不僅如此,看完電影后,你還要把一切都關掉。使用你的家庭影院竟變得如此複雜!於是你決定升級你的系統…… ### 2、實現 使用外觀模式將看電影相關的一系列操作,封裝到外觀的 watchMovie() 方法中。這樣一來,要看電影的時候,只需要進行一個“看電影”的操作就行了。同理,可將看完電影相關的一系列操作,封裝到 endMovie() 方法中。 #### (1)建立家庭影院子系統元件 ``` /** * 功放 */ public class Amplifier { /** * 開啟功放 */ public void on() { System.out.println("Top-O-Line Amplifier on"); } /** * 關閉功放 */ public void off() { System.out.println("Top-O-Line Amplifier off"); } /** * 設定DVD */ public void setDvd(DvdPlayer dvd) { System.out.println("Top-O-Line Amplifier setting DVD player to Top-O-Line DVD Player"); } /** * 設定為環繞立體聲 */ public void setSurroundSound() { System.out.println("Top-O-Line Amplifier surround sound on (5 speakers, 1 subwoofer)"); } /** * 調節音量 */ public void setVolume(int volume) { System.out.println("Top-O-Line Amplifier setting volume to " + volume); } } ``` ``` /** * DVD播放器 */ public class DvdPlayer { /** * 開啟DVD播放器 */ public void on() { System.out.println("Top-O-Line DVD Player on"); } /** * 關閉DVD播放器 */ public void off() { System.out.println("Top-O-Line DVD Player off"); } /** * 播放DVD */ public void play(String movie) { System.out.println("Top-O-Line DVD Player playing “" + movie + "”"); } /** * 停止播放DVD */ public void stop() { System.out.println("Top-O-Line DVD Player stop"); } /** * 彈出DVD */ public void eject() { System.out.println("Top-O-Line DVD Player eject"); } } ``` ``` /** * 投影儀 */ public class Projector { /** * 開啟投影儀 */ public void on() { System.out.println("Top-O-Line Projector on"); } /** * 關閉投影儀 */ public void off() { System.out.println("Top-O-Line Projector off"); } /** * 設為寬屏模式 */ public void wideScreenMode() { System.out.println("Top-O-Line Projector in widescreen mode (16x9 aspect ratio)"); } } ``` ``` /** * 影院燈光 */ public class TheaterLights { /** * 開啟燈光 */ public void on() { System.out.println("Theater Ceiling Lights on"); } /** * 調暗燈光 */ public void dim(int level) { System.out.println("Theater Ceiling Lights dimming to " + level + "%"); } } ``` ``` /** * 螢幕 */ public class Screen { /** * 放下螢幕 */ public void down() { System.out.println("Theater Screen going down"); } /** * 升起螢幕 */ public void up() { System.out.println("Theater Screen going up"); } } ``` ``` /** * 爆米花機 */ public class PopcornPopper { /** * 開啟爆米花機 */ public void on() { System.out.println("Popcorn Popper on"); } /** * 關閉爆米花機 */ public void off() { System.out.println("Popcorn Popper off"); } /** * 開始爆米花 */ public void pop() { System.out.println("Popcorn Popper popping popcorn!"); } } ``` #### (2)建立家庭影院外觀 ``` /** * 家庭影院外觀 */ public class HomeTheaterFacade { Amplifier amp; DvdPlayer dvd; Projector projector; TheaterLights lights; Screen screen; PopcornPopper popper; public HomeTheaterFacade(Amplifier amp, DvdPlayer dvd, Projector projector, TheaterLights lights, Screen screen, PopcornPopper popper) { this.amp = amp; this.dvd = dvd; this.projector = projector; this.lights = lights; this.screen = screen; this.popper = popper; } /** * 看電影 */ public void watchMovie(String movie) { System.out.println("Get ready to watch a movie..."); popper.on(); popper.pop(); lights.dim(10); screen.down(); projector.on(); projector.wideScreenMode(); amp.on(); amp.setDvd(dvd); amp.setSurroundSound(); amp.setVolume(5); dvd.on(); dvd.play(movie); } /** * 看完電影 */ public void endMovie() { System.out.println("Shuting movie theater down..."); popper.off(); lights.on(); screen.up(); projector.off(); amp.off(); dvd.stop(); dvd.eject(); dvd.off(); } } ``` #### (3)使用家庭影院外觀觀看電影 ``` public class Test { public static void main(String[] args) { // 子系統元件 Amplifier amp = new Amplifier(); DvdPlayer dvd = new DvdPlayer(); Projector projector = new Projector(); TheaterLights lights = new TheaterLights(); Screen screen = new Screen(); PopcornPopper popper = new PopcornPopper(); // 家庭影院外觀 HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, dvd, projector, lights, screen, popper); // 看電影 homeTheater.watchMovie("Raiders of the Lost Ark"); // 看完電影 homeTheater.endMovie();