外观模式
# 外观模式
# 一、外观模式
原理:外观模式是一种结构型设计模式, 能为程序库、 框架或其他复杂类提供一个简单的接口。
优缺点
- 1 优点
- 简化接口:外观模式为子系统中的一组接口提供一个简单的接口,从而简化了子系统的使用。用户不需要了解子系统的内部细节,只需要与外观类交互即可。
- 降低耦合:外观模式将客户端代码与复杂子系统解耦。客户端只需要与外观类交互,而不需要直接与子系统交互,从而降低了客户端与子系统之间的耦合度。
- 提高可维护性:由于外观类封装了子系统的复杂性,修改子系统的实现不会影响到客户端代码,只需要修改外观类即可。
- 更好的分层:外观模式有助于划分系统层次结构,分离子系统与客户端代码,增强系统的模块化设计。
- 2 缺点
- 增加额外的封装层:引入外观模式会增加系统的复杂度和额外的封装层,可能导致性能开销增加。
- 不完全符合开闭原则:在某些情况下,外观类可能需要频繁修改以适应子系统的变化,这违背了开闭原则(对扩展开放,对修改关闭)。
- 可能过度简化:外观模式可能会隐藏子系统的重要功能或灵活性,导致客户端无法使用子系统的所有功能,限制了灵活性。
适用场景
- 复杂系统的简化接口:当你需要为一个复杂的子系统提供一个简单的接口时,可以使用外观模式。
- 降低系统耦合度:当你需要将客户端代码与复杂子系统解耦时,可以使用外观模式。
- 分层设计:当你需要实现一个分层结构的系统时,可以使用外观模式来组织子系统的交互。
# 二、外观模式基本代码
TV类(子系统类)
class TV { public void on() { System.out.println("TV is on"); } public void off() { System.out.println("TV is off"); } } class SoundSystem { public void on() { System.out.println("Sound system is on"); } public void off() { System.out.println("Sound system is off"); } public void setVolume(int volume) { System.out.println("Sound system volume set to " + volume); } } class DVDPlayer { public void on() { System.out.println("DVD player is on"); } public void off() { System.out.println("DVD player is off"); } public void play(String movie) { System.out.println("Playing movie: " + movie); } }
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
37DVDPlayer类(外观类)
class HomeTheaterFacade { private TV tv; private SoundSystem soundSystem; private DVDPlayer dvdPlayer; public HomeTheaterFacade(TV tv, SoundSystem soundSystem, DVDPlayer dvdPlayer) { this.tv = tv; this.soundSystem = soundSystem; this.dvdPlayer = dvdPlayer; } public void watchMovie(String movie) { System.out.println("Get ready to watch a movie..."); tv.on(); soundSystem.on(); soundSystem.setVolume(10); dvdPlayer.on(); dvdPlayer.play(movie); } public void endMovie() { System.out.println("Shutting down the home theater..."); dvdPlayer.off(); soundSystem.off(); tv.off(); } }
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客户端代码
public class HomeTheaterTest { public static void main(String[] args) { TV tv = new TV(); SoundSystem soundSystem = new SoundSystem(); DVDPlayer dvdPlayer = new DVDPlayer(); HomeTheaterFacade homeTheater = new HomeTheaterFacade(tv, soundSystem, dvdPlayer); homeTheater.watchMovie("Inception"); System.out.println("\nMovie is over...\n"); homeTheater.endMovie(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
# 三、实现方式
- 考虑能否在现有子系统的基础上提供一个更简单的接口。 如果该接口能让客户端代码独立于众多子系统类, 那么你的方向就是正确的。
- 在一个新的外观类中声明并实现该接口。 外观应将客户端代码的调用重定向到子系统中的相应对象处。 如果客户端代码没有对子系统进行初始化, 也没有对其后续生命周期进行管理, 那么外观必须完成此类工作。
- 如果要充分发挥这一模式的优势, 你必须确保所有客户端代码仅通过外观来与子系统进行交互。 此后客户端代码将不会受到任何由子系统代码修改而造成的影响, 比如子系统升级后, 你只需修改外观中的代码即可。
- 如果外观变得过于臃肿, 你可以考虑将其部分行为抽取为一个新的专用外观类。
编辑 (opens new window)