外观模式是一种结构性设计模式, 通过为复杂的子系统提供一个统一的接口, 使得子系统更容易使用.

外观模式结构

  • 外观: 提供一个高层接口, 供客户使用, 它知道哪些子系统负责处理请求, 并将客户的请求委派给适当的子系统
  • 子系统类: 实现子系统的功能, 处理由外观指派的任务

外观模式实现

假设有一个复杂的家庭影院系统, 包括DVD, 投影仪, 音响, 灯光等系统, 可以通过外观模式来模拟这个系统的实现

class DVDPlayer {
public void on() {
System.out.println("DVD Player is on");
}

public void play(String movie) {
System.out.println("Playing " + movie);
}

public void off() {
System.out.println("DVD Player is off");
}
}

class Projector {
public void on() {
System.out.println("Projector is on");
}

public void off() {
System.out.println("Projector is off");
}
}

class Sound {
public void on() {
System.out.println("Sound is on");
}

public void setVolume(int level) {
System.out.println("Setting sound volume to " + level);
}

public void off() {
System.out.println("Sound is off");
}
}

class Light {
public void on() {
System.out.println("Lights are on");
}

public void dim(int level) {
System.out.println("Dimming lights to " + level + "%");
}

public void off() {
System.out.println("Lights are off");
}
}

class HomeTheaterFacade {
private DVDPlayer dvdPlayer;
private Projector projector;
private SoundSystem soundSystem;
private Light light;

public HomeTheaterFacade(DVDPlayer dvdPlayer, Projector projector, SoundSystem soundSystem, Light light) {
this.dvdPlayer = dvdPlayer;
this.projector = projector;
this.soundSystem = soundSystem;
this.light = light;
}

public void watchMovie(String movie) {
System.out.println("Get ready to watch a movie...");
light.dim(10);
projector.on();
soundSystem.on();
soundSystem.setVolume(5);
dvdPlayer.on();
dvdPlayer.play(movie);
}

public void endMovie() {
System.out.println("Shutting down movie theater...");
dvdPlayer.off();
soundSystem.off();
projector.off();
light.on();
}
}

public class Client {
public static void main(String[] args) {
DVDPlayer dvdPlayer = new DVDPlayer();
Projector projector = new Projector();
SoundSystem soundSystem = new SoundSystem();
Light light = new Light();

HomeTheaterFacade homeTheater = new HomeTheaterFacade(dvdPlayer, projector, soundSystem, light);
homeTheater.watchMovie("Inception");
homeTheater.endMovie();
}
}

优点:

  • 降低了子系统与客户端的耦合度, 子系统的变化不会影响客户类
  • 对客户屏蔽了子系统组件, 减少了客户处理的对象数目, 子系统使用起来更容易

缺点:

  • 不符合开闭原则