一、定义
外观模式: 提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
这个定义清楚的告诉我们,外观的意图是要提供一个简单的接口,好让一个子系统更易于使用。从这个模式的类图可以感受到这一点。
相关代码如下:
public class Amplifier {
public void on() {
System.out.println("Amplifier on");
}
public void setDvd(DvdPlayer dvd) {
System.out.println("Amplifier setDvd");
}
public void setSurroundSound() {
System.out.println("Amplifier setSurroundSound");
}
public void setVolume(int volume) {
System.out.println("Amplifier setVolume");
}
public void off() {
System.out.println("Amplifier off");
}
}
public class CdPlayer {
// 有一些方法
}
public class DvdPlayer {
// 有一些方法
}
public class PopcornPopper {
// 有一些方法
}
public class Projector {
// 有一些方法
}
public class Screen {
// 有一些方法
}
/**
* 外观
*/
public class HomeTheaterFacade {
private Amplifier amplifier;
private Tuner tuner;
private DvdPlayer dvdPlayer;
private CdPlayer cdPlayer;
private PopcornPopper popper;
private Screen screen;
private TheaterLights lights;
private Projector projector;
public HomeTheaterFacade(Amplifier amplifier, Tuner tuner, DvdPlayer dvdPlayer, CdPlayer cdPlayer, PopcornPopper popper, Screen screen, TheaterLights lights, Projector projector) {
this.amplifier = amplifier;
this.tuner = tuner;
this.dvdPlayer = dvdPlayer;
this.cdPlayer = cdPlayer;
this.popper = popper;
this.screen = screen;
this.lights = lights;
this.projector = projector;
}
public void watchMovie(String movie) {
System.out.println("get ready to watch a movie: " + movie);
popper.on();
popper.pop();
lights.dim(10);
screen.down();
projector.on();
projector.wideScreenMode();
amplifier.on();
amplifier.setDvd(dvdPlayer);
amplifier.setSurroundSound();
amplifier.setVolume(11);
dvdPlayer.on();
dvdPlayer.play(movie);
}
public void endMovie() {
System.out.println("Shutting movie theater down");
popper.off();
lights.on();
screen.up();
projector.off();
amplifier.off();
dvdPlayer.stop();
dvdPlayer.eject();
dvdPlayer.off();
}
}
/**
* 测试类
*/
public class HomeTheaterTest {
public static void main(String[] args) {
Amplifier amplifier = new Amplifier();
Tuner tuner = new Tuner();
Projector projector = new Projector();
Screen screen = new Screen();
PopcornPopper popper = new PopcornPopper();
TheaterLights theaterLights = new TheaterLights();
DvdPlayer dvdPlayer = new DvdPlayer();
CdPlayer cdPlayer = new CdPlayer();
HomeTheaterFacade facade = new HomeTheaterFacade(amplifier, tuner, dvdPlayer, cdPlayer, popper, screen, theaterLights, projector);
facade.watchMovie("音乐之声");
facade.endMovie();
}
}
使用到的设计原则
- 最少知识原则
二、总结要点
- 当需要简化并统一一个很大的接口或者一群复杂的接口时,使用外观模式。
- 外观模式将客户从一个复杂的子系统中解耦。
- 实现一个外观,需要将子系统组合进外观中,然后将工作委托给子系统执行。
- 你可以为一个子系统实现多个外观。
- 通常来讲,仅需要一个外观对象,因此Facade对象通常属于单例模式。
三、应用场景
- Java日志门面(SLF4J):SLF4J(Simple Logging Facade for Java)是一个日志门面框架,它提供了一组统一的日志API(如
org.slf4j.Logger),客户端代码只需依赖SLF4J接口,而无需关心底层具体日志实现(如Logback、Log4j等)。