外观模式
外观(Facade、门面)模式属于结构型模式的一种。
外观模式给客户端提供一个统一入口,并对外屏蔽内部子系统的调用细节。
外观模式通过为一组复杂的接口提供一个统一的高层接口,使得客户端与子系统之间的交互变得更加简单。外观模式旨在将客户端与多个复杂子系统的交互进行解耦,客户端无需了解子系统的内部实现细节,只需要通过外观类提供的接口与系统进行交互。
子系统类不会意识到外观的存在, 它们在系统内运作并且相互之间可直接进行交互。
如果我们想拥有某个功能,但是这个功能是在多个子系统中相互有交叉,我们并不想去改动子系统中代码。此时,我们就可以使用外观模式,建一个外观类,在外观类中去调用多个子系统中的方法,而我们使用时,只需调用外观类即可。
外观模式相当于一个中介。
我们经常说的网关Gateway,本质上也是一个Facade。
外观模式通常有以下组成部分:
- 外观类(Facade):为复杂子系统提供一个简化的接口,客户端通过它与系统进行交互。
- 子系统类(Subsystem):实现子系统的具体功能,但通常这些类不直接与客户端交互。
- 客户端(Client):通过外观类与系统进行交互,不直接接触子系统。
假如我们有个复杂的观影系统,包括多个子系统(例如,DVD播放器、音响和投影仪)。我们通过外观模式来简化操作。
1、定义子系统类
// DVD 播放器
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() {
System.out.println("DVD is playing");
}
public void stop() {
System.out.println("DVD is stopped");
}
}
// 音响系统
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 level) {
System.out.println("Setting sound volume to " + level);
}
}
// 投影仪
class Projector {
public void on() {
System.out.println("Projector is ON");
}
public void off() {
System.out.println("Projector is OFF");
}
public void focus() {
System.out.println("Projector is focused");
}
}
2、创建外观类
class HomeTheaterFacade {
private DVDPlayer dvdPlayer;
private SoundSystem soundSystem;
private Projector projector;
public HomeTheaterFacade(DVDPlayer dvd, SoundSystem sound, Projector proj) {
this.dvdPlayer = dvd;
this.soundSystem = sound;
this.projector = proj;
}
public void watchMovie() {
System.out.println("Get ready to watch a movie...");
projector.on();
projector.focus();
soundSystem.on();
soundSystem.setVolume(5);
dvdPlayer.on();
dvdPlayer.play();
}
public void endMovie() {
System.out.println("Shutting down the movie theater...");
dvdPlayer.stop();
dvdPlayer.off();
soundSystem.off();
projector.off();
}
}
3、客户端
public class Client {
public static void main(String[] args) {
// 创建子系统
DVDPlayer dvd = new DVDPlayer();
SoundSystem sound = new SoundSystem();
Projector projector = new Projector();
// 创建外观类
HomeTheaterFacade homeTheater = new HomeTheaterFacade(dvd, sound, projector);
// 客户端通过外观类进行操作
homeTheater.watchMovie();
System.out.println("\n--- Movie is Over ---\n");
homeTheater.endMovie();
}
}
外观模式的优缺点。
优点:
- 简化调用:外观模式通过提供一个统一的接口,简化了与复杂系统的交互。
- 减少依赖:客户端代码无需知道子系统的内部细节,降低了系统之间的耦合度。
- 提高可维护性:如果子系统的内部实现发生变化,只要外观类保持不变,客户端代码不需要进行修改。
缺点:
- 外观类可能成为与程序中所有类都耦合的对象。
使用外观模式时,客户端不需要关心子系统的具体实现,而是通过外观类来简化操作,提高了系统的可维护性和灵活性。
欲让其亡,先令其狂。-- 烟沙九洲