《HeadFirst设计模式》读书笔记-第7章-外观模式
2017-04-20 23:44
225 查看
定义
外观模式(facade pattern)提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更加容易使用。从上面的图可以看出,Facade类对子系统进行了一下封装,客户只需要和Facade类打交道,不需要接触子系统中的各个类,也不需要了解子系统中各个类间的关系。从这个角度来说,客户也就从组件中的子系统中解耦了,不需要依赖于子系统中具体的类了。
外观模式的一个重要的目的就是简化系统,提供给客户一个简单的接口,方便客户使用。
代码实现
例子是为家庭影院构造外观,让观看电影的步骤尽可能地简单。下图给出了类图。首先看看HomeTheaterFacade这个高层接口,它提供了6个接口分别执行6个动作,每个动作是通过调用子系统中其它的类来实现的。
public class HomeTheaterFacade { Amplifier amp; // 功放 Tuner tuner; // 电子调音器 DvdPlayer dvd; // CdPlayer cd; // Projector projector; // 投影机 TheaterLights lights; // 剧场灯光 Screen screen; // 屏幕 PopcornPopper popper; // 爆米花机 public HomeTheaterFacade(Amplifier amp, Tuner tuner, DvdPlayer dvd, CdPlayer cd, Projector projector, Screen screen, TheaterLights lights, PopcornPopper popper) { this.amp = amp; this.tuner = tuner; this.dvd = dvd; this.cd = cd; this.projector = projector; this.screen = screen; this.lights = lights; this.popper = popper; } // 开始观看名为“movie”的电影接口 public void watchMovie(String movie) { System.out.println("Get ready to watch a movie..."); popper.on(); // 打开爆米花机 popper.pop(); // 开始爆米花 lights.dim(10); // 调低灯光亮度为10% screen.down(); // 放下屏幕 projector.on(); // 打开投影机 projector.wideScreenMode(); // 设置宽屏模式 amp.on(); // 打开功放 amp.setDvd(dvd); amp.setSurroundSound(); // 设置环绕立体声 amp.setVolume(5); // 设置音量 dvd.on(); // 打开DVD播放器 dvd.play(movie); // 开始播放电影 } public void endMovie() { System.out.println("Shutting movie theater down..."); popper.off(); lights.on(); screen.up(); projector.off(); amp.off(); dvd.stop(); dvd.eject(); // 弹出Dvd播放器 dvd.off(); } public void listenToCd(String cdTitle) { System.out.println("Get ready for an audiopile experence..."); lights.on(); amp.on(); amp.setVolume(5); amp.setCd(cd); amp.setStereoSound(); cd.on(); cd.play(cdTitle); } public void endCd() { System.out.println("Shutting down CD..."); amp.off(); amp.setCd(cd); cd.eject(); cd.off(); } public void listenToRadio(double frequency) { System.out.println("Tuning in the airwaves..."); tuner.on(); tuner.setFrequency(frequency); amp.on(); amp.setVolume(5); amp.setTuner(tuner); } public void endRadio() { System.out.println("Shutting down the tuner..."); tuner.off(); amp.off(); } }
因为子系统中类太多了,这里只列出一个,其它的类似。
public class Amplifier { String description; Tuner tuner; DvdPlayer dvd; CdPlayer cd; public Amplifier(String description) { this.description = description; } public void on() { System.out.println(description + " on"); } public void off() { System.out.println(description + " off"); } public void setStereoSound() { System.out.println(description + " stereo mode on"); } public void setSurroundSound() { System.out.println(description + " surround sound on (5 speakers, 1 subwoofer)"); } public void setVolume(int level) { System.out.println(description + " setting volume to " + level); } public void setTuner(Tuner tuner) { System.out.println(description + " setting tuner to " + dvd); this.tuner = tuner; } public void setDvd(DvdPlayer dvd) { System.out.println(description + " setting DVD player to " + dvd); this.dvd = dvd; } public void setCd(CdPlayer cd) { System.out.println(description + " setting CD player to " + cd); this.cd = cd; } public String toString() { return description; } }
测试驱动代码,也是客户代码:
public class HomeTheaterTestDrive { public static void main(String[] args) { Amplifier amp = new Amplifier("Top-O-Line Amplifier"); Tuner tuner = new Tuner("Top-O-Line AM/FM Tuner", amp); DvdPlayer dvd = new DvdPlayer("Top-O-Line DVD Player", amp); CdPlayer cd = new CdPlayer("Top-O-Line CD Player", amp); Projector projector = new Projector("Top-O-Line Projector", dvd); TheaterLights lights = new TheaterLights("Theater Ceiling Lights"); Screen screen = new Screen("Theater Screen"); PopcornPopper popper = new PopcornPopper("Popcorn Popper"); HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, tuner, dvd, cd, projector, screen, lights, popper); // 客户开始/停止看电影只要调用高层接口的Api即可 // 不需要和子系统中其它类交互 // 当然客户需要调用子系统中某个类时,也是允许的 homeTheater.watchMovie("Raiders of the Lost Ark"); homeTheater.endMovie(); } }
本章金句
外观模式不只是简化了子系统的接口,也将客户从组件的子系统中解耦外观只是对子系统的接口进行了更高层次的抽象,客户还是可以直接调用子系统中的类的,当然一般情况这是不必要的,只要外观接口定义的好
外观模式符合“最少知识原则”
适配器模式和外观模式的差别:
两种模式都是对其它的接口的再次封装。差别在适配器强调对一个或者多个接口的转换,而外观模式则强调简化接口
相关文章推荐
- HeadFirst设计模式_读书笔记_007_外观模式
- 【深入PHP 面向对象】读书笔记(十) - 让面向对象编程更加灵活的模式(三) - 外观模式
- 【设计模式】《Head First 设计模式》读书笔记——外观模式
- 读书笔记-外观模式又叫门面模式
- 【读书笔记】将外观模式写好了与大家分享(C#,C++)
- 【读书笔记】HeadFirst设计模式——单件不简单:详述实现Singleton模式需要考虑的方方面面
- HeadFirst设计模式_读书笔记_001_策略模式
- HeadFirst设计模式_读书笔记_009_ 组合模式
- 读《HeadFirst设计模式》笔记之外观模式
- 《HeadFirst设计模式》读书笔记-第3章-装饰者模式
- 适配器模式Adapter、外观模式Facade-- 学习HeadFirst设计模式记录
- 《HeadFirst设计模式》读书笔记-第2章-观察者模式
- 《Android源码设计模式》读书笔记 (22) 第22章 外观模式
- 《HeadFirst设计模式》读书笔记-第8章-模板方法模式
- 《HeadFirst设计模式》读书笔记-第7章-适配器模式
- 【读书笔记】HeadFirst设计模式——命令模式简述
- 设计模式读书笔记-----外观模式
- HeadFirst设计模式_读书笔记_002_观察者模式
- HeadFirst设计模式_读书笔记_010_状态模式