文章目錄
設計模式-外觀模式
1. 案例引出外觀模式
影院管理項目,
組建一個家庭影院其中包括DVD 播放器、投影儀、自動屏幕、環繞立體聲、爆米花機,
要求完成使用家庭影院的功能,其過程爲:
- 直接用遙控器:統籌各設備開關
- 開爆
米花機Popcorn
- 放下
屏幕Screen
- 開
投影儀Projector
- 開
音響Stereo
- 開 DVD,選 DVD
- 去拿爆米花
- 調暗
燈光TheaterLight
- 播放
- 觀影結束後,關閉各種設備
傳統方式解決影院管理
然後再關閉各種設備就完成了,其中的很明顯調用的方法太多,我們不方便調用。
傳統方式解決影院管理問題分析
- 在
ClientTest
的 main 方法中,創建各個子系統的對象,並直接去調用子系統(對象)相關方法,會造成調用過程混亂,沒有清晰的過程
- 不利於在
ClientTest
中,去維護對子系統的操作- 解決思路: 定義一個高層接口,給 子系統中的一組接口提供一個一致的界面(比如在高層接口提供四個方法ready, play, pause, end ),用來訪問子系統中的一羣接口。也就是說就是通過定義一個一致的接口(界面類),用以屏蔽內部子系統的細節,使得調用端只需跟這個接口發生調用,而無需關心這個子系統的內部細節,這就要使用到
設計模式中的外觀模式
了。
2. 外觀模式
2.1 外觀模式基本介紹
外觀模式(Facade),也叫“過程模式:
外觀模式爲子系統中的一組接口
提供一個一致的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。- 外觀模式通過定義一個一致的接口,用 以
屏蔽內部子系統的細節,
使得 調用端只需跟這個接口發生調用,而無需關心這個子系統的內部細節。
2.2 外觀模式原理類圖
外觀類(Facade):
爲調用端提供統一的調用接口, 外觀類知道哪些子系統負責處理請求,從而將調用端的請求代理給適當子系統對象。調用者(Client):
外觀接口的調用者。子系統的集合:
指模塊或者子系統,處理 Facade 對象指派的任務,他是功能的實際提供者
2.3 外觀模式解決影院管理
- 外觀模式可以理解爲轉換一羣接口,客戶只要調用一個接口,而不用調用多個接口才能達到目的。比如:在
pc
上安裝軟件的時候經常有一鍵安裝選項(省去選擇安裝目錄、安裝的組件等等),還有就是手機的重啓功能(把關機和啓動合爲一個操作)。- 外觀模式就是解決多個複雜接口帶來的使用困難,起到簡化用戶操作的作用。
2.4 代碼實現
創建應用對象
播放器DVDPlayer
public class DVDPlayer {
// 私有化構造器
private DVDPlayer(){
}
// 使用單例模式, 使用餓漢式
private static DVDPlayer instance = new DVDPlayer();
public static DVDPlayer getInstanc() {
return instance;
}
public void on() {
System.out.println(" 打開DVD...");
}
public void off() {
System.out.println(" 關閉DVD...");
}
public void play() {
System.out.println(" 播放電影...");
}
public void pause() {
System.out.println(" 暫停電影...");
}
}
投影儀Projector
public class Projector {
// 私有化構造器
private Projector(){
}
private static Projector instance = new Projector();
public static Projector getInstance() {
return instance;
}
public void on() {
System.out.println(" 打開投影儀... ");
}
public void off() {
System.out.println(" 關閉投影儀... ");
}
public void focus() {
System.out.println(" 投影儀正在工作... ");
}
}
音響Stereo
public class Stereo {
// 私有化構造器
private Stereo(){
}
private static Stereo instance = new Stereo();
public static Stereo getInstance() {
return instance;
}
public void on() {
System.out.println(" 打開音響... ");
}
public void off() {
System.out.println(" 關閉音響... ");
}
}
爆米花機Popcorn
public class Popcorn {
// 私有化構造器
private Popcorn(){
}
private static Popcorn instance = new Popcorn();
public static Popcorn getInstance() {
return instance;
}
public void on() {
System.out.println(" 打開爆米花機...");
}
public void off() {
System.out.println(" 關閉爆米花機... ");
}
public void pop() {
System.out.println(" 製作爆米花中...");
}
}
屏幕Screen
public class Screen {
// 私有化構造器
private Screen(){
}
private static Screen instance = new Screen();
public static Screen getInstance() {
return instance;
}
public void up() {
System.out.println(" 放映結束,升起顯示屏...");
}
public void down() {
System.out.println(" 開始放映,放下顯示屏...");
}
}
燈光TheaterLight
public class TheaterLight {
// 私有化構造器
private TheaterLight(){
}
private static TheaterLight instance = new TheaterLight();
public static TheaterLight getInstance() {
return instance;
}
public void on() {
System.out.println(" 打開燈光...");
}
public void off() {
System.out.println(" 關閉燈光...");
}
public void dim() {
System.out.println(" 調暗燈光... ");
}
public void bright() {
System.out.println(" 調亮燈光...");
}
}
外觀類Facade
public class HomeTheaterFacade {
//定義各個子系統對象
private TheaterLight theaterLight;
private Popcorn popcorn;
private Stereo stereo;
private Projector projector;
private Screen screen;
private DVDPlayer dVDPlayer;
//構造器
public HomeTheaterFacade() {
super();
this.theaterLight = TheaterLight.getInstance();
this.popcorn = Popcorn.getInstance();
this.stereo = Stereo.getInstance();
this.projector = Projector.getInstance();
this.screen = Screen.getInstance();
this.dVDPlayer = DVDPlayer.getInstanc();
}
// 準備工作
public void ready() {
// 打開爆米花機,製作爆米花
popcorn.on();
popcorn.pop();
// 放下屏幕
screen.down();
// 打開投影儀
projector.on();
// 打開音響
stereo.on();
// 打開DVD
dVDPlayer.on();
// 調暗燈光
theaterLight.dim();
}
// 播放DVD
public void play() {
dVDPlayer.play();
}
// 暫停DVD
public void pause() {
dVDPlayer.pause();
}
// 觀影結束,關閉各種設備
public void end() {
// 關閉爆米花機
popcorn.off();
// 打開燈光
theaterLight.bright();
// 升起屏幕
screen.up();
// 關閉投影儀
projector.off();
// 關閉音響
stereo.off();
// 關閉DVD
dVDPlayer.off();
}
}
Client
Client就是用戶,是不是感覺這麼複雜的操作用戶操作起來感覺很簡單,這就是外觀模式的力量。
public class Client {
public static void main(String[] args) {
HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();
homeTheaterFacade.ready();
homeTheaterFacade.play();
homeTheaterFacade.end();
}
}
2.5 外觀模式的細節
- 外觀模式對外屏蔽了子系統的細節,因此外觀模式降低了客戶端對子系統使用的複雜性。
- 外觀模式對客戶端與子系統的耦合關係 - 解耦,讓子系統內部的模塊更易維護和擴展。
通過合理的使用外觀模式,可以幫我們更好的劃分訪問的層次。
當系統需要進行分層設計時,可以考慮使用 Facade 模式。
- 在維護一個遺留的大型系統時,可能這個系統已經變得非常難以維護和擴展,此時可以考慮爲新系統開發一個Facade 類,來提供遺留系統的比較清晰簡單的接口,讓新系統與 Facade 類交互,提高複用性。
- 不能過多的或者不合理的使用外觀模式,使用外觀模式好,還是直接調用模塊好。要以讓系統有層次,利於維護爲目的。