
设计模式之外观模式
甜蜜的家庭影院
在我们进入外观模式的细节之前,让我们看一个风行全美的热潮:建立自己的家庭影院。你组装了一套杀手级的系统,内含DVD播放器、投影机、自动屏幕、环绕立体声,甚至还有爆米花机。
看看我们的组件:
1 2 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); } }
|
1 2 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"); } }
|
1 2 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"); } }
|
1 2 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); } }
|
1 2 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。。。
累死人了,打开这么多开关。。。。没错看完电影还要将这些关掉。让我们看看外观模式如何来解决这团混乱,好让你能轻易的享受电影。。。
构造家庭影院的外观
让我们逐步构造家庭影院外观:第一步是使用组合让外观能够访问子系统中所有的组件。
1 2 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(); } }
|
观赏电影(用轻松的方式)
1 2 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(); } }
|
定义外观模式
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
“最少知识”原则
最少知识原则告诉我们要减少对象之间的交互,只留下几个“密友”。这个原则通常是这么说的:
最少知识原则:只和你的密友谈话。
这个原则希望我们在设计中,不要让太多的类耦合在一起,免得修改系统中的一部分,会影响到其他部分。如果许多类之间相互依赖,那么这个系统就会变成一个易碎的系统,它需要花许多成本维护,也会因为太复杂而不容易被其他人理解。
总结
- 当需要简化并统一一个很大的接口或则一群复杂的接口时,使用外观
- 外观将客户从一个复杂的子系统中解耦
- 实现一个外观,需要将子系统组合进外观中,然后将工作委托给子系统执行
- 你可以为一个子系统实现一个以上的外观