《Head First 設計模式》:外觀模式
阿新 • • 發佈:2020-08-25
# 正文
## 一、定義
外觀模式提供了一個統一的介面,用來訪問子系統中的一群介面。外觀定義了一個高層介面,讓子系統更容易使用。
**要點:**
* 外觀模式將一個或數個類的複雜的一切都隱藏在背後,只顯露出一個乾淨美好的外觀。
* 通過將子系統的方法封裝到外觀的方法中,可以達到對子系統的“一鍵操作”。
* 外觀模式的意圖是簡化介面,好讓一個子系統更易於使用。
* 外觀模式將客戶從元件的子系統中解耦。
## 二、實現步驟
### 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();