设计模式中的外观模式(Facade Pattern)是一种简化系统接口的模式,它通过提供一个统一的高层接口来访问子系统中的一群接口。这种模式可以提高系统的可维护性和可扩展性,同时降低了客户端与多个子系统之间的耦合度。下面是一个详细的介绍和Java代码示例,该示例描述了一个家庭影院系统,包括电视、DVD播放机、立体声音响等多个组件,以及一个外观类来简化这些组件的操作。
一、外观模式的作用
外观模式主要用于以下几种情况:
1、简化接口
当一个系统变得非常复杂,并且客户端需要一个简单的接口来与之交互。
2、降低依赖
通过引入外观类,可以减少系统之间的依赖性。
3、封装变化
如果子系统中的接口发生变化,可以通过调整外观类来应对,而不需要改变客户端代码。
4、遵循迪米特法则
一个软件实体应当尽可能少地与其他实体发生相互作用。
二、外观模式的角色
1、子系统类(Subsystem Classes):
它们可以接受请求。
2、外观类(Facade Class):
提供一个简单的接口给客户端。
三、java代码示例
1、子系统类定义
首先定义各个子系统类:
java
public class DVDPlayer {
private String description;
public DVDPlayer(String description) {
this.description = description;
}
public void on() {
System.out.println(description + " 开启");
}
public void off() {
System.out.println(description + " 关闭");
}
public void eject() {
System.out.println(description + " 弹出光盘");
}
public void playMovie(String movie) {
System.out.println(description + " 播放电影 " + movie);
}
}
public class TV {
private String description;
public TV(String description) {
this.description = description;
}
public void on() {
System.out.println(description + " 开启");
}
public void off() {
System.out.println(description + " 关闭");
}
public void setChannel(int channel) {
System.out.println(description + " 设置频道到 " + channel);
}
}
public class Amplifier {
private String description;
public Amplifier(String description) {
this.description = description;
}
public void on() {
System.out.println(description + " 开启");
}
public void off() {
System.out.println(description + " 关闭");
}
public void setVolume(int level) {
System.out.println(description + " 设置音量到 " + level);
}
}
public class PopcornPopper {
private String description;
public PopcornPopper(String description) {
this.description = description;
}
public void on() {
System.out.println(description + " 开启");
}
public void off() {
System.out.println(description + " 关闭");
}
public void pop() {
System.out.println(description + " 开始爆米花制作");
}
}
2、外观类定义
接下来定义一个遥控器的外观类,用来简化用户对家庭影院系统的操作:
java
public class HomeTheaterFacade {
private DVDPlayer dvdPlayer;
private TV tv;
private Amplifier amplifier;
private PopcornPopper popcornPopper;
public HomeTheaterFacade(DVDPlayer dvdPlayer, TV tv, Amplifier amplifier, PopcornPopper popcornPopper) {
this.dvdPlayer = dvdPlayer;
this.tv = tv;
this.amplifier = amplifier;
this.popcornPopper = popcornPopper;
}
public void watchMovie(String movie) {
System.out.println("准备观看电影 " + movie);
popcornPopper.on();
popcornPopper.pop();
dvdPlayer.on();
dvdPlayer.playMovie(movie);
tv.on();
tv.setChannel(1); // 假设频道1是HDMI输入
amplifier.on();
amplifier.setVolume(5);
}
public void endMovie() {
System.out.println("电影结束,关闭所有设备...");
popcornPopper.off();
dvdPlayer.off();
tv.off();
amplifier.off();
}
}
3、使用外观模式
最后,在主程序中使用这个外观模式:
java
public class HomeTheaterTestDrive {
public static void main(String[] args) {
DVDPlayer dvdPlayer = new DVDPlayer("DVD播放机");
TV tv = new TV("电视机");
Amplifier amplifier = new Amplifier("音响");
PopcornPopper popcornPopper = new PopcornPopper("爆米花机");
HomeTheaterFacade homeTheater = new HomeTheaterFacade(dvdPlayer, tv, amplifier, popcornPopper);
homeTheater.watchMovie("Matrix");
homeTheater.endMovie();
}
}
4、详细解释
在这个家庭影院系统中,我们有四个主要的组件:DVD播放机、电视机、立体声音响以及爆米花机。每个组件都有自己的开关、播放等功能。如果我们想要看一部电影,我们需要分别操作这些设备,这可能会很麻烦。因此,我们创建了一个HomeTheaterFacade
类来简化这个过程。
HomeTheaterFacade
类充当了客户端和子系统之间的中介者,它负责协调子系统中的各个部分,以便客户端可以通过一个简单的接口来控制整个家庭影院系统。这样做的好处是显而易见的:首先,客户端的代码变得更简单,因为它们只需要与一个对象打交道;其次,如果未来需要更改子系统的行为,只需要修改HomeTheaterFacade
类,而不需要改动客户端代码。
四、扩展
在现实世界的应用中,外观模式是非常有用的。例如,在一个大型企业级应用程序中,可能有许多不同的模块和服务,每个模块都有一组复杂的API。对于外部用户来说,直接使用这些API可能是困难的。这时候就可以使用外观模式来提供一个友好的接口,使得外部用户可以更容易地使用这些服务。
此外,外观模式还可以用来实现分层的设计。例如,在一个Web应用程序中,前端页面可能需要从多个后端服务获取数据。通过创建一个外观层,可以将这些服务的调用抽象化,使得前端页面只需要与一个统一的服务接口进行交互,而不需要关心具体的数据是从哪里来的。
五、总结
外观模式过提供一个统一的接口来简化对多个子系统的调用,从而使得系统的使用变得更加容易。在实际项目中,您可以根据需要扩展更多子系统以及它们的功能,从而减少代码的复杂度和长度。