
设计模式之外观模式
甜蜜的家庭影院
在我们进入外观模式的细节之前,让我们看一个风行全美的热潮:建立自己的家庭影院。你组装了一套杀手级的系统,内含DVD播放器、投影机、自动屏幕、环绕立体声,甚至还有爆米花机。
看看我们的组件:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 
 | 
 
 
 
 public class Amplifier {
 private Tuner tuner;
 private DvdPlayer dvdPlayer;
 private CdPlayer cdPlayer;
 
 public void on() {
 System.out.println("Amplifier on");
 }
 
 public void off() {
 System.out.println("Amplifier off");
 }
 
 public void setCd() {
 System.out.println("Amplifier setCd");
 }
 
 public void setDvd(DvdPlayer dvdPlayer) {
 this.dvdPlayer = dvdPlayer;
 }
 
 public void setStereoSound() {
 System.out.println("Amplifier setStereoSound");
 }
 
 public void setSurroundSound() {
 System.out.println("Amplifier setSurroundSound");
 }
 
 public void setTuner() {
 System.out.println("Amplifier setTuner");
 }
 
 public void setVolume(int i) {
 System.out.println("Amplifier setVolume " + i);
 }
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 
 | 
 
 
 
 public class DvdPlayer {
 private Amplifier amplifier;
 public void on() {
 System.out.println("DvdPlayer on");
 }
 public void off() {
 System.out.println("DvdPlayer off");
 }
 
 public void eject() {
 System.out.println("DvdPlayer eject");
 }
 
 public void pause() {
 System.out.println("DvdPlayer pause");
 }
 
 public void play(String movie) {
 System.out.println("DvdPlayer play " + movie);
 }
 
 public void setSurroundAudio() {
 System.out.println("DvdPlayer setSurroundAudio");
 }
 
 public void setTwoChannelAudio() {
 System.out.println("DvdPlayer setTwoChannelAudio");
 }
 
 public void stop() {
 System.out.println("DvdPlayer stop");
 }
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | 
 
 
 
 public class Projector {
 private DvdPlayer dvdPlayer;
 
 public void on() {
 System.out.println("Projector on");
 }
 
 public void off() {
 System.out.println("Projector off");
 }
 
 public void tvMode() {
 System.out.println("Projector tvMode");
 }
 
 public void wideScreenMode() {
 System.out.println("Projector wideScreenMode");
 }
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | 
 
 
 
 public class TheaterLights {
 public void on() {
 System.out.println("TheaterLights on");
 }
 
 public void off() {
 System.out.println("TheaterLights off");
 }
 
 public void dim(int i) {
 System.out.println("TheaterLights dim " + i);
 }
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | 
 
 
 
 public class PopcornPopper {
 public void on() {
 System.out.println("PopcornPopper on");
 }
 
 public void off() {
 System.out.println("PopcornPopper off");
 }
 
 public void pop() {
 System.out.println("PopcornPopper pop");
 }
 }
 
 | 
你花了几个星期布线、挂上投影机、连接所有的装置并进行微调。现在,你准备开始享受一部电影……
观赏电影(用困难的方式)
挑选一部DVD影片,然后先执行一些任务。
打开爆米花机、开始爆米花、将灯光调暗、放下屏幕、打开投影机、将投影机 的输入切换到DVD、将投影机设置在宽屏模式、打开功放、将功放的输入设置为DVD、将功放设置为环绕立体声、调节功放音量、打开DVD播放器、开始播放DVD。。。
累死人了,打开这么多开关。。。。没错看完电影还要将这些关掉。让我们看看外观模式如何来解决这团混乱,好让你能轻易的享受电影。。。
构造家庭影院的外观
让我们逐步构造家庭影院外观:第一步是使用组合让外观能够访问子系统中所有的组件。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 
 | 
 
 
 
 public class HomeTheaterFacade {
 private final Amplifier amplifier;
 private final Tuner tuner;
 private final DvdPlayer dvdPlayer;
 private final CdPlayer cdPlayer;
 private final Projector projector;
 private final TheaterLights theaterLights;
 private final Screen screen;
 private final PopcornPopper popcornPopper;
 
 public HomeTheaterFacade(Amplifier amplifier, Tuner tuner, DvdPlayer dvdPlayer,
 CdPlayer cdPlayer, Projector projector,
 TheaterLights theaterLights, Screen screen,
 PopcornPopper popcornPopper) {
 this.amplifier = amplifier;
 this.tuner = tuner;
 this.dvdPlayer = dvdPlayer;
 this.cdPlayer = cdPlayer;
 this.projector = projector;
 this.theaterLights = theaterLights;
 this.screen = screen;
 this.popcornPopper = popcornPopper;
 }
 
 
 public void watchMovie(String movie) {
 System.out.println("Get Ready to watch a movie....");
 popcornPopper.on();
 popcornPopper.pop();
 theaterLights.dim(10);
 screen.down();
 projector.on();
 projector.wideScreenMode();
 amplifier.on();
 amplifier.setDvd(dvdPlayer);
 amplifier.setSurroundSound();
 amplifier.setVolume(5);
 dvdPlayer.on();
 dvdPlayer.play(movie);
 }
 
 
 public void endMovie() {
 System.out.println("Shutting movie theater down...");
 popcornPopper.off();
 theaterLights.on();
 screen.up();
 projector.off();
 amplifier.off();
 dvdPlayer.stop();
 dvdPlayer.eject();
 dvdPlayer.off();
 }
 }
 
 | 
观赏电影(用轻松的方式)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | public class HomeTheaterTestDrive {public static void main(String[] args) {
 
 Amplifier amplifier = new Amplifier();
 Tuner tuner = new Tuner();
 DvdPlayer dvdPlayer = new DvdPlayer();
 CdPlayer cdPlayer = new CdPlayer();
 Projector projector = new Projector();
 TheaterLights theaterLights = new TheaterLights();
 Screen screen = new Screen();
 PopcornPopper popcornPopper = new PopcornPopper();
 
 
 HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(amplifier, tuner, dvdPlayer,
 cdPlayer, projector, theaterLights, screen, popcornPopper);
 
 
 homeTheaterFacade.watchMovie("Raiders of the Lost Ark");
 
 homeTheaterFacade.endMovie();
 }
 }
 
 | 
定义外观模式
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
“最少知识”原则
最少知识原则告诉我们要减少对象之间的交互,只留下几个“密友”。这个原则通常是这么说的:
最少知识原则:只和你的密友谈话。
这个原则希望我们在设计中,不要让太多的类耦合在一起,免得修改系统中的一部分,会影响到其他部分。如果许多类之间相互依赖,那么这个系统就会变成一个易碎的系统,它需要花许多成本维护,也会因为太复杂而不容易被其他人理解。
总结
- 当需要简化并统一一个很大的接口或则一群复杂的接口时,使用外观
- 外观将客户从一个复杂的子系统中解耦
- 实现一个外观,需要将子系统组合进外观中,然后将工作委托给子系统执行
- 你可以为一个子系统实现一个以上的外观