【图解设计模式系列】The Facade Pattern: 外观模式
外观模式通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。外观模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

外观模式包含如下几个角色:
外观(Facade)角色 :为多个子系统对外提供一个共同的接口。
子系统(SubSystem)角色 :实现系统的部分功能,客户可以通过外观角色访问它。
实例
搭建一个家庭影院系统,系统内包含设备:DVD播放器、投影机、自动屏幕、立体声音响、爆米花机。
定义这些媒体类:
class Amplifier{
public void on(){
System.out.println("欢迎使用功放类。。");
}
public void off(){
System.out.println("已经关闭功放。。");
}
public void setCD(){
System.out.println("正在安放CD。。。");
}
public void setDVD(){
System.out.println("正在安放DVD、。。");
}
public void setStereoSound(){
System.out.println("设置立体声。。");
}
public void setSurroundSound(){
System.out.println("设置环绕立体声。。");
}
public void setTime(){
System.out.println("正在设置时间。。");
}
public void setVolume(){
System.out.println("正在设置音量。。");
}
}
//定义Tuner类
class Tuner{
public void on(){
System.out.println("正在 打开调谐器。。");
}
public void off(){
System.out.println("正在关闭调谐器。。");
}
public void setAM(){
System.out.println("正在设置am。。");
}
public void setFM(){
System.out.println("正在设置频道。。");
}
public void setFrequency(){
System.out.println("正咋设置频道。。");
}
}
//定义DVD播放器类
class DVDPlayer{
public void on(){
System.out.println("正在打开DVD。。");
}
public void off(){
System.out.println("正在关闭DVD。。");
}
public void pause(){
System.out.println("已经暂停DVD播放。。");
}
public void play(){
System.out.println("正在播放DVD。。");
}
public void setTwoChannelAudio(){
System.out.println("正在设置双频道。。");
}
public void setSurroundAudio(){
System.out.println("正在设置环绕立体声。。");
}
}
//定义CD播放器
class CDPlayer{
public void on(){
System.out.println("正在打开CD");
}
public void off(){
System.out.println("正在关闭CD");
}
public void eject(){
System.out.println("弹出CD播放器!");
}
public void pause(){
}
public void play(){
}
public String toString(){
return "hello panda";
}
}
//定义投影仪
class Projector{
public void on(){
System.out.println("正在打开投影仪。。");
}
public void off(){
System.out.println("正在关闭投影仪。。");
}
public void setTVMode(){
System.out.println("正在设置tv模式。。");
}
public void setWideScreenMode(){
System.out.println("正在设置宽屏模式。。");
}
}
//定义屏幕
class Screen{
public void up(){
System.out.println("正在生起屏幕。。");
}
public void down(){
System.out.println("正在放下屏幕。。");
}
}
//定义爆米花机
class PopcornPopper{
public void on(){
System.out.println("正在打开爆米花机。。");
}
public void off(){
System.out.println("正在关闭爆米花机。。");
}
public void pop(){
System.out.println("正在蹦爆米花。。");
}
}
//定义影院灯光
class TheaterLights{
public void on(){
System.out.println("正在打开灯光。。");
}
public void off(){
System.out.println("正在关闭灯光。。");
}
public void dim(){
System.out.println("正在调暗灯光。。");
}
}
外观模式类:俩方法,一个看电影-打开一系列设备,一个电影结束-关闭一系列设备
//定义外观模式家庭影院
class HomeTheaterFacade{
Amplifier amp;
Tuner tuner ;
DVDPlayer dvd;
CDPlayer cd;
Projector project;
TheaterLights light;
Screen screen;
PopcornPopper pop;
//构造的时候拿到这些对象
public HomeTheaterFacade(Amplifier amp,Tuner tuner,DVDPlayer dvd,
CDPlayer cd ,Projector project,TheaterLights light,Screen screen
,PopcornPopper pop){
this.amp = amp;
this.tuner = tuner;
this.dvd = dvd;
this.cd = cd;
this.project = project;
this.light = light;
this.screen = screen;
this.pop = pop;
}
//看电影 放一个方法里来执行一系列动作
public void watchMovie(String movie){
System.out.println("get ready to watch a movie..");
pop.on();//首先打开爆米花机
pop.pop();//然后蹦爆米花
light.dim();//把灯光调暗
screen.down();//投影仪放下来
project.on();
project.setWideScreenMode();
amp.on();
amp.setDVD();
amp.setSurroundSound();
amp.setVolume();
dvd.on();
dvd.play();
}
//电影结束
public void endMovie(String movie){
System.out.println("shutting movie theater down..");
pop.off();
light.on();
screen.up();
project.off();
amp.off();
dvd.off();
}
}
客户端
public class FacadePattern {
public static void main(String args[]){
Amplifier amp = new Amplifier();
Tuner tuner = new Tuner() ;
DVDPlayer dvd = new DVDPlayer();
CDPlayer cd = new CDPlayer();
Projector project = new Projector();;
TheaterLights light = new TheaterLights();
Screen screen = new Screen();
PopcornPopper pop = new PopcornPopper();
HomeTheaterFacade facade = new HomeTheaterFacade(amp,tuner,dvd,cd,project,light,screen,pop);
facade.watchMovie("movie");
facade.endMovie("movie");
}
}
通过上面的代码可以看出,每个类对象都要执行一些方法,如果直接new这些类创建对象去调方法会与这些类产生耦合,这时单独再写一个外观类,构造初始化时拿到这些类对象,在一个方法里去调这些类对象的方法,这样对客户来说只和一个类打交道,与子系统的一堆类解耦了。此类原则即为:最少知识原则。
客户端只和外观谈话,不和子设备,如DVD播放机、投影仪等谈话,降低了客户端和设备的耦合度。

浙公网安备 33010602011771号