設計模式:外觀模式 (Facade)
7 分鐘
Facade 為複雜的子系統提供一個簡化的入口,讓客戶端不必知道底下究竟是怎麼運作的。
意圖與用途
想像要播放一部電影,需要:
- 開啟投影機
- 開啟音響系統
- 調暗燈光、放下窗簾
- 設定串流播放器
客戶端其實只想呼叫 homeTheater.startMovie(movie) 就好。Facade 把這一連串協調工作,全包進一個乾淨的方法裡。
結構與角色
- Facade:簡化的介面,負責協調各個子系統
- Subsystem classes:複雜的內部實作,對 Facade 一無所知
實作範例:家庭劇院系統
TypeScript
class Projector {
on(): void { console.log('Projector on'); }
off(): void { console.log('Projector off'); }
setInput(source: string): void { console.log(`Projector input: ${source}`); }
}
class SoundSystem {
on(): void { console.log('Sound system on'); }
off(): void { console.log('Sound system off'); }
setVolume(level: number): void { console.log(`Volume: ${level}`); }
}
class Lights {
dim(level: number): void { console.log(`Lights dimmed to ${level}%`); }
on(): void { console.log('Lights on'); }
}
class Blinds {
down(): void { console.log('Blinds down'); }
up(): void { console.log('Blinds up'); }
}
class StreamingPlayer {
play(movie: string): void { console.log(`Playing: ${movie}`); }
stop(): void { console.log('Stopped'); }
}
// Facade
class HomeTheaterFacade {
constructor(
private projector: Projector,
private sound: SoundSystem,
private lights: Lights,
private blinds: Blinds,
private player: StreamingPlayer,
) {}
startMovie(movie: string): void {
console.log('—— 電影開始 ——');
this.lights.dim(10);
this.blinds.down();
this.projector.on();
this.projector.setInput('HDMI');
this.sound.on();
this.sound.setVolume(40);
this.player.play(movie);
}
endMovie(): void {
console.log('—— 電影結束 ——');
this.player.stop();
this.sound.off();
this.projector.off();
this.blinds.up();
this.lights.on();
}
}
// 客戶端只需要知道 Facade
const theater = new HomeTheaterFacade(
new Projector(), new SoundSystem(), new Lights(), new Blinds(), new StreamingPlayer()
);
theater.startMovie('Inception');
// 之後...
theater.endMovie();客戶端只寫兩行,所有協調工作都藏在 Facade 裡。
適用情境
適用時機
- 複雜的子系統需要一個簡化的對外 API
- 想為某個常見流程提供單一的進入點
- 要把內部子系統與外部層隔離開來
注意
Facade 並不禁止客戶端在需要更細緻的控制時,直接存取子系統。它是一層便利層,而不是一道鎖。
總結
Facade 的價值在於簡化。它不在乎內部有多複 —— 負責提供一個乾淨、一致的入口,把協調的細節藏起來。
在實務上,SDK 設計、分層架構的邊界,以及各種服務層級的抽象,都不斷地用到這個模式。