外观模式

什么是外观模式

提供一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用

一个使用了外观模式的小例子

在这里我们使用了对象之间的组合
我们想要在看电影的时候让爆米花机工作然后把各种音响设备调成打开状态,没有使用外观模式之前我们要一个一个设备区打开,然后看完了之后我们要再一个一个设备区关闭,这很麻烦,有没有可能然我们有一键打开和一键关闭呢?接下来的小例子也许能帮我们实现
首先我们有一些设备

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
/**
* 放大器
*/
public class Amplifier {
Tuner tuner;
DvdPlayer dvdPlayer;
CdPlayer cdPlayer;
void on(){
System.out.println("放大器打开");
}
void off(){
System.out.println("放大器关闭");
}
void setCd(CdPlayer cdPlayer){
this.cdPlayer = cdPlayer;
System.out.println("设置cd");
cdPlayer.on();
}
void setDvd(DvdPlayer dvdPlayer){
this.dvdPlayer = dvdPlayer;
System.out.println("设置dvd");
dvdPlayer.on();
}
//立体声
void setStereoSound(){
System.out.println("设置立体声");
}
//环绕声
void setSurroundSound(){
System.out.println("设置环绕声");
}
void setTuner(){
System.out.println("Tuner调音");
tuner.on();
}
void setVolume(int numbner){
System.out.println("调节音量"+numbner);
}
}

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
/**
* CD播放器
*/
public class CdPlayer {
Amplifier amplifier;
public CdPlayer(Amplifier amplifier){
this.amplifier = amplifier;
}
void on(){
System.out.println("cd打开");
}
void off(){
System.out.println("cd关闭");
}
void eject(){
System.out.println("弹出cd");
}
void pause(){
System.out.println("cd暂停");
}
void play(){
System.out.println("cd播放");
}
void stop(){
System.out.println("cd停止");
}
}
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
/**
* Dvd播放器
*/
public class DvdPlayer {
Amplifier amplifier;
public DvdPlayer(Amplifier amplifier){
this.amplifier = amplifier;
}
void on(){
System.out.println("Dvd打开");
}
void off(){
System.out.println("Dvd关闭");
}
void eject(){
System.out.println("弹出dvd");
}
void pause(){
System.out.println("dvd暂停");
}
void play(String movie){
System.out.println("Dvd播放"+movie);
}
void setSurroundAudio(){
System.out.println("设置dvd环绕音");
}
void setTwoChannelAudio(){
System.out.println("双通道音频设置");
}
void stop(){
System.out.println("dvd停止");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 爆米花机
*/
public class PopcornPopper {
void on(){
System.out.println("打开爆米花机");
}
void off(){
System.out.println("关闭爆米花机");
}
void pop(){
System.out.println("制作爆米花");
}
}
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
/**
* 投影仪
*/
public class Projector {
DvdPlayer dvdPlayer;
public Projector(DvdPlayer dvdPlayer){
this.dvdPlayer = dvdPlayer;
}
void on(){
System.out.println("打开投影仪");
}
void off(){
System.out.println("关闭投影仪");
}
void tvMode(){
System.out.println("投影仪设置为tv模式");
}
void wideScreeenMode(){
System.out.println("投影仪设置为屏幕模式");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
/**
* 屏幕
*/
public class Screen {
void up(){
System.out.println("屏幕收起");
}
void down(){
System.out.println("屏幕放下");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 剧场灯光
*/
public class TheaterLights {
void on(){
System.out.println("打开剧场灯光");
}
void off(){
System.out.println("关闭剧场灯光");
}
void dim(int number){
System.out.println("昏暗灯光模式"+number);
}
}
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
/**
* 调音
*/
public class Tuner {
Amplifier amplifier;
public Tuner(Amplifier amplifier){
this.amplifier = amplifier;
}
void on(){
System.out.println("调音器打开");
}
void off(){
System.out.println("调音器关闭");
}
void setAm(){
System.out.println("am调频");
}
void setFm(){
System.out.println("fm调频");
}
void setFrequency(){
System.out.println("设置频率");
}
}

好了,我们的设备现在已经有了,就要开始用外观模式来打开这些家庭影院了

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 amplifier;
Tuner tuner;
DvdPlayer dvdPlayer;
CdPlayer cdPlayer;
Projector projector;
TheaterLights theaterLights;
Screen screen;
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("准备开始看电影咯");
popcornPopper.on();
popcornPopper.pop();
theaterLights.dim(10);
screen.down();
projector.on();
projector.wideScreeenMode();
amplifier.on();
amplifier.setDvd(dvdPlayer);
amplifier.setSurroundSound();
amplifier.setVolume(5);
dvdPlayer.on();
dvdPlayer.play(movie);
}
public void endMovie(){
System.out.println("关闭电影");
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
public class HomeTheaterTest {
public static void main(String[] args){
Amplifier amplifier = new Amplifier();
Tuner tuner = new Tuner(amplifier);
DvdPlayer dvdPlayer = new DvdPlayer(amplifier);
CdPlayer cdPlayer = new CdPlayer(amplifier);
Projector projector = new Projector(dvdPlayer);
Screen screen = new Screen();
TheaterLights theaterLights = new TheaterLights();
PopcornPopper popcornPopper = new PopcornPopper();
HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(amplifier,tuner,dvdPlayer,cdPlayer,projector,theaterLights,screen,popcornPopper);
homeTheaterFacade.watchMovie("肖申克的救赎");
System.out.println("----------");
homeTheaterFacade.endMovie();
}
}

准备开始看电影咯
打开爆米花机
制作爆米花
昏暗灯光模式10
屏幕放下
打开投影仪
投影仪设置为屏幕模式
放大器打开
设置dvd
Dvd打开
设置环绕声
调节音量5
Dvd打开
Dvd播放肖申克的救赎
这里是分割线————
关闭电影
关闭爆米花机
打开剧场灯光
屏幕收起
关闭投影仪
放大器关闭
dvd停止
弹出dvd
Dvd关闭

总结

1.当需要简化并统一一个很大的接口或者一群复杂的接口的时候我们使用外观模式
2.外观模式将客户从一个复杂的子系统中解耦
3.实现一个外观需要将子系统组合进外观中,然后将工作委托给子系统执行
4.我们可以为子系统实现一个以上的外观