12. 設計模式-外觀模式

設計模式-外觀模式

1. 案例引出外觀模式

影院管理項目,組建一個家庭影院其中包括DVD 播放器、投影儀、自動屏幕、環繞立體聲、爆米花機,要求完成使用家庭影院的功能,其過程爲:

  1. 直接用遙控器:統籌各設備開關
  2. 開爆米花機Popcorn
  3. 放下屏幕Screen
  4. 投影儀Projector
  5. 音響Stereo
  6. 開 DVD,選 DVD
  7. 去拿爆米花
  8. 調暗燈光TheaterLight
  9. 播放
  10. 觀影結束後,關閉各種設備

傳統方式解決影院管理

在這裏插入圖片描述

然後再關閉各種設備就完成了,其中的很明顯調用的方法太多,我們不方便調用。

傳統方式解決影院管理問題分析

  1. ClientTest 的 main 方法中,創建各個子系統的對象,並直接去調用子系統(對象)相關方法,會造成調用過程混亂,沒有清晰的過程
  2. 不利於在 ClientTest 中,去維護對子系統的操作
  3. 解決思路: 定義一個高層接口,給 子系統中的一組接口提供一個一致的界面(比如在高層接口提供四個方法ready, play, pause, end ),用來訪問子系統中的一羣接口。也就是說就是通過定義一個一致的接口(界面類),用以屏蔽內部子系統的細節,使得調用端只需跟這個接口發生調用,而無需關心這個子系統的內部細節,這就要使用到設計模式中的外觀模式了。

2. 外觀模式

2.1 外觀模式基本介紹
  1. 外觀模式(Facade),也叫“過程模式:外觀模式爲子系統中的一組接口 提供一個一致的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
  2. 外觀模式通過定義一個一致的接口,用 以屏蔽內部子系統的細節,使得 調用端只需跟這個接口發生調用,而無需關心這個子系統的內部細節。
2.2 外觀模式原理類圖
  • 外觀類(Facade): 爲調用端提供統一的調用接口, 外觀類知道哪些子系統負責處理請求,從而將調用端的請求代理給適當子系統對象。
  • 調用者(Client): 外觀接口的調用者。
  • 子系統的集合:指模塊或者子系統,處理 Facade 對象指派的任務,他是功能的實際提供者
    在這裏插入圖片描述
2.3 外觀模式解決影院管理
  1. 外觀模式可以理解爲轉換一羣接口,客戶只要調用一個接口,而不用調用多個接口才能達到目的。比如:在 pc上安裝軟件的時候經常有一鍵安裝選項(省去選擇安裝目錄、安裝的組件等等),還有就是手機的重啓功能(把關機和啓動合爲一個操作)。
  2. 外觀模式就是解決多個複雜接口帶來的使用困難,起到簡化用戶操作的作用。
  3. 在這裏插入圖片描述
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 外觀模式的細節
  1. 外觀模式對外屏蔽了子系統的細節,因此外觀模式降低了客戶端對子系統使用的複雜性。
  2. 外觀模式對客戶端與子系統的耦合關係 - 解耦,讓子系統內部的模塊更易維護和擴展。
  3. 通過合理的使用外觀模式,可以幫我們更好的劃分訪問的層次。
  4. 當系統需要進行分層設計時,可以考慮使用 Facade 模式。
  5. 在維護一個遺留的大型系統時,可能這個系統已經變得非常難以維護和擴展,此時可以考慮爲新系統開發一個Facade 類,來提供遺留系統的比較清晰簡單的接口,讓新系統與 Facade 類交互,提高複用性。
  6. 不能過多的或者不合理的使用外觀模式,使用外觀模式好,還是直接調用模塊好。要以讓系統有層次,利於維護爲目的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章