外观模式(Facade pattern),是软件工程中常用的一种软件设计模式,它为子系统中的一组界面提供一个统一的高层界面,使得子系统更容易使用。
定义
一个改变接口的新模式,但是它改变接口的原因是为了简化接口。这个模式被巧妙地命名为外观模式,之所以这么称呼,是因为它将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的外观。
想要使用外观模式,我们创建了一个接口简化而统一的类,用来包装子系统中一个或多个复杂的类。外观模式相当直接,很容易理解,这方面和许多其他的模式不太一样。但这并不会降低它的威力:外观模式允许我们让客户和子系统之间避免紧耦合。
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
OO原则
最少知识原则:只和你的密友谈话。
结构
- Facade 这个外观类为子系统中Packages 1、2、3提供一个共同的对外界面(接口)
- Clients 客户对象通过一个外观界面读写子系统中各界面的数据资源。
- Packages 客户可以通过外观界面读取的内部库。
实现
在进入外观模式的细节之前,让我们看如何建立自己的家庭影院。通过一番研究比较,你组装了一套杀手级的系统,内含DVD播放器、投影机、自动屏幕、环绕立体声,甚至还有爆米花机。
你花了好几个星期布线、挂上投影机、连接所有的装置并进行微调。现在,你准备开始享受一部电影……
家庭影院观影过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// 打开爆米花机,开始爆米花
popper.on();
popper.pop();
// 灯光调到10%的亮度
lights.dim(10);
// 把屏幕放下来
screen.down();
// 打开投影机,并将它设置在宽屏模式
projector.on();
projector.setInput(dvd);
projector.wideScreenMode();
// 打开功放,设置为DVD,调整成环绕立体声模式,音量调到5
amp.on();
amp.setDvd(dvd);
amp.setSurroundSound();
amp.setVolume(5);
// 打开DVD机,“终于”可以看电影了!
dvd.on();
dvd.play(movies);
|
外观
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 {
// 这就是组合:我们会用到的子系统组件全部在这里
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,
TheaterLights lights,
Screen screen,
PopcornPopper popper) {
this.amp = amp;
this.tuner = tuner;
this.dvd = dvd;
this.cd = cd;
this.projector = projector;
this.lights = lights;
this.screen = screen;
this.popper = popper;
}
public void watchMovie(String movie){
// watchMovie()将我们之前手动进行的每项任务依次处理。
// 请注意,每项任务都是委托子系统中相应的组件处理的。
System.out.println("Get ready to watch " + movie);
popper.on();
popper.pop();
lights.dim(10);
screen.down();
projector.on();
projector.wideScreenMode();
amp.on();
amp.setDvd(dvd);
amp.setSurroundSound();
amp.setVolume(5);
dvd.on();
dvd.play(movie);
}
public void endMovie(){
// endMovie()负责关闭一切。每项任务也是委托子系统中合适的组件处理的。
System.out.println("Shutting movie theater down");
popper.off();
lights.on();
screen.up();
projector.off();
amp.off();
dvd.stop();
dvd.eject();
dvd.off();
}
}
|
测试
1
2
3
|
HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(amp, tuner, dvd, cd, projector, lights, screen, popper);
homeTheaterFacade.watchMovie("Pulp Fiction");
homeTheaterFacade.endMovie();
|
附录