外观模式是一种结构型设计模式,提供了一个简化系统接口的高层接口,使得系统更加易于使用。外观模式隐藏了系统的复杂性,并为客户端提供了一个简单的接口,使得客户端与系统之间的交互更加简单和直接。
结构
- 外观类(Facade): 包含了客户端可能需要调用的各种子系统的功能,负责将客户端的请求转发给适当的子系统对象。
public class Facade {
private Subsystem1 subsystem1;
private Subsystem2 subsystem2;
private Subsystem3 subsystem3;
public Facade() {
this.subsystem1 = new Subsystem1();
this.subsystem2 = new Subsystem2();
this.subsystem3 = new Subsystem3();
}
public void operation() {
subsystem1.operation();
subsystem2.operation();
subsystem3.operation();
}
}
- 子系统类(Subsystem): 包含了系统的各个模块,负责处理外观类指派的任务,但不包含外观类的引用。
public class Subsystem1 {
public void operation() {
System.out.println("Subsystem1 operation.");
}
}
public class Subsystem2 {
public void operation() {
System.out.println("Subsystem2 operation.");
}
}
public class Subsystem3 {
public void operation() {
System.out.println("Subsystem3 operation.");
}
}
优点和缺点
优点:
- 简化接口: 外观模式提供了一个简化的接口,隐藏了系统的复杂性,使得客户端更容易使用系统。
- 解耦合: 外观模式将客户端与系统的组件解耦合,客户端不需要知道系统内部的结构和功能。
- 易于使用: 外观模式使得系统更易于使用,客户端只需要调用外观类的方法,而不需要直接和多个子系统交互。
缺点:
- 不符合开闭原则: 如果需要添加新的子系统或者修改子系统的行为,可能需要修改外观类,不符合开闭原则。
示例
以下是一个外观模式的示例,假设有一个家庭影院系统,其中包含了多个设备(灯光、投影仪、音响等),通过外观模式,提供了一个简化的接口给客户端操作家庭影院。
// 子系统类
class Light {
void turnOn() {
System.out.println("Light is ON");
}
void turnOff() {
System.out.println("Light is OFF");
}
}
class Projector {
void turnOn() {
System.out.println("Projector is ON");
}
void turnOff() {
System.out.println("Projector is OFF");
}
}
class SoundSystem {
void turnOn() {
System.out.println("Sound System is ON");
}
void turnOff() {
System.out.println("Sound System is OFF");
}
}
// 外观类
class HomeTheaterFacade {
private Light light;
private Projector projector;
private SoundSystem soundSystem;
HomeTheaterFacade(Light light, Projector projector, SoundSystem soundSystem) {
this.light = light;
this.projector = projector;
this.soundSystem = soundSystem;
}
void watchMovie() {
System.out.println("Get ready to watch a movie...");
light.turnOn();
projector.turnOn();
soundSystem.turnOn();
}
void endMovie() {
System.out.println("Movie is finished. Shutting down the home theater...");
light.turnOff();
projector.turnOff();
soundSystem.turnOff();
}
}
// 客户端代码
public class Main {
public static void main(String[] args) {
Light light = new Light();
Projector projector = new Projector();
SoundSystem soundSystem = new SoundSystem();
HomeTheaterFacade homeTheater = new HomeTheaterFacade(light, projector, soundSystem);
// 开始观影
homeTheater.watchMovie();
// 结束观影
homeTheater.endMovie();
}
}
在这个例子中,HomeTheaterFacade 提供了 watchMovie 和 endMovie 两个方法,客户端只需要调用这两个方法就可以完成开启和关闭家庭影院的操作,而不需要了解家庭影院内部设备的复杂操作。