定义
外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用于访问子系统中一组复杂的接口。外观模式将子系统的复杂性隐藏在一个高层接口后面,使得客户端可以通过简单的方式与子系统进行交互,而不需要了解子系统的内部实现细节。
外观模式包括以下角色:
- 外观(Facade):外观对象是客户端与子系统之间的接口,它封装了对子系统的访问,提供了一个简单的高层接口,用于隐藏子系统的复杂性。
- 子系统(Subsystems):子系统是一组实现具体功能的类或对象,外观模式通过封装子系统的功能,提供了一个更简单的接口给客户端使用。
外观模式的主要优点包括:
- 简化接口:外观模式通过封装复杂的子系统,提供了一个简单的接口给客户端使用,减少了客户端与子系统之间的直接耦合。
- 提高可维护性:外观模式将子系统的复杂性封装起来,降低了修改子系统的风险,提高了系统的可维护性。
- 提升了系统的松耦合性:外观模式将客户端与子系统之间解耦,使得它们可以独立演化,降低了依赖关系。
然而,外观模式也有一些缺点:
- 违反开闭原则:当需求变化时,可能需要修改外观类的代码,这可能会影响到客户端的调用代码。
- 不能满足所有需求:外观模式是一种简化接口的方式,但并不一定能够满足所有客户端的需求,有些特殊需求可能还需要直接访问子系统。
外观模式在实际开发中经常被使用,特别是当系统中存在复杂的子系统并且需要提供一个简化的接口给客户端使用时,外观模式可以起到很好的作用。
示例一:家庭影院系统
下面是一个使用 Java 编写的外观模式的示例,我们以一个家庭影院系统为例:
首先,定义家庭影院子系统的各个组件类:
class DVDPlayer {
public void on() {
System.out.println("DVD Player is turned on");
}
public void play(String movie) {
System.out.println("DVD Player is playing movie: " + movie);
}
public void stop() {
System.out.println("DVD Player is stopped");
}
public void off() {
System.out.println("DVD Player is turned off");
}
}
class Projector {
public void on() {
System.out.println("Projector is turned on");
}
public void setInput(String input) {
System.out.println("Projector input is set to: " + input);
}
public void wideScreenMode() {
System.out.println("Projector is in wide screen mode");
}
public void off() {
System.out.println("Projector is turned off");
}
}
class SurroundSoundSystem {
public void on() {
System.out.println("Surround Sound System is turned on");
}
public void setVolume(int volume) {
System.out.println("Surround Sound System volume is set to: " + volume);
}
public void off() {
System.out.println("Surround Sound System is turned off");
}
}
class Lights {
public void dim() {
System.out.println("Lights are dimmed");
}
public void off() {
System.out.println("Lights are turned off");
}
}
然后,定义外观类 HomeTheaterFacade,封装了家庭影院子系统的操作:
class HomeTheaterFacade {
private DVDPlayer dvdPlayer;
private Projector projector;
private SurroundSoundSystem soundSystem;
private Lights lights;
public HomeTheaterFacade(DVDPlayer dvdPlayer, Projector projector, SurroundSoundSystem soundSystem, Lights lights) {
this.dvdPlayer = dvdPlayer;
this.projector = projector;
this.soundSystem = soundSystem;
this.lights = lights;
}
public void watchMovie(String movie) {
System.out.println("Get ready to watch a movie...");
lights.dim();
projector.on();
projector.setInput("DVD");
projector.wideScreenMode();
soundSystem.on();
soundSystem.setVolume(10);
dvdPlayer.on();
dvdPlayer.play(movie);
}
public void endMovie() {
System.out.println("Shutting down the home theater...");
dvdPlayer.stop();
dvdPlayer.off();
soundSystem.off();
projector.off();
lights.off();
}
}
最后,我们可以使用外观模式来简化家庭影院系统的操作:
public class FacadePatternExample {
public static void main(String[] args) {
// 创建各个子系统的对象
DVDPlayer dvdPlayer = new DVDPlayer();
Projector projector = new Projector();
SurroundSoundSystem soundSystem = new SurroundSoundSystem();
Lights lights = new Lights();
// 创建外观对象,并传入子系统对象
HomeTheaterFacade homeTheater = new HomeTheaterFacade(dvdPlayer, projector, soundSystem, lights);
// 使用外观对象操作家庭影院系统
homeTheater.watchMovie("Avengers: Endgame");
System.out.println("------------------------------------");
homeTheater.endMovie();
}
}
运行上述示例代码,输出如下:
Get ready to watch a movie...
Lights are dimmed
Projector is turned on
Projector input is set to: DVD
Projector is in wide screen mode
Surround Sound System is turned on
Surround Sound System volume is set to: 10
DVD Player is turned on
DVD Player is playing movie: Avengers: Endgame
------------------------------------
Shutting down the home theater...
DVD Player is stopped
DVD Player is turned off
Surround Sound System is turned off
Projector is turned off
Lights are turned off
在示例中,我们定义了家庭影院子系统的各个组件类,如 DVDPlayer、Projector、SurroundSoundSystem 和 Lights。然后,我们创建了一个外观类 HomeTheaterFacade,它封装了对子系统的操作。通过 HomeTheaterFacade,我们可以通过调用 watchMovie 方法开始观影,调用 endMovie 方法结束观影。
通过使用外观模式,客户端代码不需要直接与各个子系统组件进行交互,而是通过简单调用外观类的方法来操作整个家庭影院系统。这样,我们可以隐藏子系统的复杂性,提供一个简单的接口给客户端使用,使得客户端更加便捷地操作家庭影院系统。
示例二:智能家居系统
假设我们有一个智能家居系统,其中包含多个设备和传感器,例如灯光控制、温度调节、窗帘控制等。我们可以使用外观模式将这些设备和传感器封装起来,提供一个简单的接口给用户控制整个智能家居系统。
首先,定义智能家居系统的各个子系统组件类:
class Light {
public void turnOn() {
System.out.println("Lights are turned on");
}
public void turnOff() {
System.out.println("Lights are turned off");
}
}
class Thermostat {
public void setTemperature(int temperature) {
System.out.println("Thermostat temperature is set to: " + temperature);
}
}
class Curtain {
public void open() {
System.out.println("Curtains are opened");
}
public void close() {
System.out.println("Curtains are closed");
}
}
然后,定义外观类 SmartHomeFacade,封装智能家居系统的操作:
class SmartHomeFacade {
private Light light;
private Thermostat thermostat;
private Curtain curtain;
public SmartHomeFacade(Light light, Thermostat thermostat, Curtain curtain) {
this.light = light;
this.thermostat = thermostat;
this.curtain = curtain;
}
public void leaveHome() {
System.out.println("Leaving home...");
light.turnOff();
thermostat.setTemperature(20);
curtain.close();
}
public void returnHome() {
System.out.println("Returning home...");
light.turnOn();
thermostat.setTemperature(25);
curtain.open();
}
}
最后,我们可以使用外观模式来简化智能家居系统的操作:
public class FacadePatternExample {
public static void main(String[] args) {
// 创建各个子系统的对象
Light light = new Light();
Thermostat thermostat = new Thermostat();
Curtain curtain = new Curtain();
// 创建外观对象,并传入子系统对象
SmartHomeFacade smartHome = new SmartHomeFacade(light, thermostat, curtain);
// 使用外观对象操作智能家居系统
smartHome.leaveHome();
System.out.println("------------------------------------");
smartHome.returnHome();
}
}
运行以上代码,输出如下:
Leaving home...
Lights are turned off
Thermostat temperature is set to: 20
Curtains are closed
------------------------------------
Returning home...
Lights are turned on
Thermostat temperature is set to: 25
Curtains are opened
在上述示例中,我们定义了智能家居系统的各个子系统组件类,如 Light、Thermostat 和 Curtain。然后,我们创建了一个外观类 SmartHomeFacade,它封装了对子系统的操作。通过 SmartHomeFacade,我们可以通过调用 leaveHome 方法离开家,调用 returnHome 方法回家。
通过使用外观模式,客户端代码不需要直接与各个子系统组件进行交互,而是通过简单调用外观类的方法来操作整个智能家居系统。这样,我们可以隐藏子系统的复杂性,提供一个简单的接口给用户控制整个智能家居系统。用户可以通过调用外观类的方法来一次性完成多个设备的操作,从而实现对智能家居系统的便捷控制。