外观模式-Facade
外观模式通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。外观模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
一、类图
外观模式包含如下几个角色:
- 外观(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播放机、投影仪等谈话,降低了客户端和设备的耦合度。
……更多设计模式的内容,可以访问Refactoring.Guru
不积跬步,无以至千里。不积小流,无以成江海!