定义:
外观模式是简化用户和子系统进行交互的成熟模式,外观模式的关键是为子系统提供一个称作外观的类,该外观类的实例负责和子系统中类的实例打交道。当用户想要和子系统中的若干个类的实例打交道时,可以代替地和子系统的外观类的实例打交道,用户不必了解子系统中的细节。
当系统需要进行分层设计时,可以考虑使用Facade模式,可以帮我们更好的划分访问的层次,还可以维护一个遗留的大型系统。
角色分析:
子系统(Subsystem):子系统是若干个类的集合,这些类的实例协同合作为用户提供所需要的功能,子系统中任何类都不包含外观类的实例引用。(处理Facade对象指派的任务,功能的实际提供者)
外观(Facade):外观是一个类,包含子系统中全部或部分类的实例引用,当用户想要和子系统中的若干个类的实例打交道时,可以代替地和子系统的外观类的实例打交道。(为调用端提供统一的调用)
示例代码:
- 子系统(Subsystem)
Stereo.java
public class Stereo {
private static Stereo instance=new Stereo();
public static Stereo getInstance() {
return instance;
}
public void on() {
System.out.println("Stereo on");
}
public void off() {
System.out.println("Stereo off");
}
public void up() {
System.out.println("Screen up");
}
public void down() {
System.out.println("Screen down");
}
}
Popcorn.java
public class Popcorn {
private static Popcorn instance=new Popcorn();
public static Popcorn getInstance() {
return instance;
}
public void on() {
System.out.println("popcorn on");
}
public void off() {
System.out.println("popcorn off");
}
public void pop() {
System.out.println("popcorn is poping");
}
}
DVDplayer.java
public class DVDplayer {
private static DVDplayer instance=new DVDplayer();
public static DVDplayer getInstance() {
return instance;
}
public void on() {
System.out.println("DVD on");
}
public void off() {
System.out.println("DVD off");
}
public void play() {
System.out.println("DVD id playing");
}
public void pause() {
System.out.println("DVD pause");
}
}
Projector.java
public class Projector {
private static Projector instance=new Projector();
public static Projector getInstance() {
return instance;
}
public void on() {
System.out.println("Projector on");
}
public void off() {
System.out.println("Projector off");
}
public void focus() {
System.out.println("Projector is focus");
}
}
TheaterLight.java
public class TheaterLight {
private static TheaterLight instance=new TheaterLight();
public static TheaterLight getInstance() {
return instance;
}
public void on() {
System.out.println("TheaterLight on");
}
public void off() {
System.out.println("TheaterLight off");
}
public void dim() {
System.out.println("TheaterLight dim");
}
public void bright() {
System.out.println("TheaterLight bright");
}
}
Screen.java
public class Screen {
private static Screen instance=new Screen();
public static Screen getInstance() {
return instance;
}
public void on() {
System.out.println("Screen up");
}
public void off() {
System.out.println("Screen down");
}
}
- 外观(Facade)
HomeTheaterFacade.java
public class HomeTheaterFacade {
private TheaterLight theaterLight;
private Popcorn popcorn;
private Stereo stereo;
private Projector projector;
private Screen screen;
private DVDplayer dvDplayer;
HomeTheaterFacade() {
super();
this.theaterLight = TheaterLight.getInstance();
this.popcorn = Popcorn.getInstance();
this.stereo = Stereo.getInstance();
this.projector = Projector.getInstance();
this.screen = Screen.getInstance();
this.dvDplayer = DVDplayer.getInstance();
}
public void ready() {
popcorn.on();
popcorn.pop();
screen.on();
projector.on();
stereo.on();
dvDplayer.on();
theaterLight.dim();
}
public void play() {
dvDplayer.play();
}
public void pause() {
dvDplayer.pause();
}
public void end() {
popcorn.off();
theaterLight.bright();
screen.off();
projector.off();
stereo.off();
dvDplayer.off();
}
}
测试类(用户使用):
facadeClient.java
public class facadeClient {
private TheaterLight theaterLight;
private Popcorn popcorn;
private Stereo stereo;
private Projector projector;
private Screen screen;
private DVDplayer dvDplayer;
public facadeClient() {
super();
this.theaterLight = TheaterLight.getInstance();
this.popcorn = Popcorn.getInstance();
this.stereo = Stereo.getInstance();
this.projector = Projector.getInstance();
this.screen = Screen.getInstance();
this.dvDplayer = DVDplayer.getInstance();
}
public void oldMethod() {
popcorn.on();
popcorn.pop();
screen.on();
projector.on();
stereo.on();
dvDplayer.on();
theaterLight.dim();
System.out.println("-------------------------------------");
dvDplayer.play();
System.out.println("-------------------------------------");
dvDplayer.pause();
System.out.println("-------------------------------------");
popcorn.off();
theaterLight.bright();
screen.off();
projector.off();
stereo.off();
dvDplayer.off();
}
public static void main(String[] args) {
//当系统需要进行分层设计时,可以考虑使用Facade模式,可以帮我们更好的划分访问的层次(此例 就是ready,play,pause,end四个层次),使得代码更加灵活
//在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个Facade类,来提供遗留系统的比较清晰简单的接口,让新系统与Facade交互
HomeTheaterFacade homeTheaterFacade=new HomeTheaterFacade();//这个是使用外观类的新方法,只需要4个步骤就可以完成一次看电影
homeTheaterFacade.ready();
System.out.println("-------------------------------------");
homeTheaterFacade.play();
System.out.println("-------------------------------------");
homeTheaterFacade.pause();
System.out.println("-------------------------------------");
homeTheaterFacade.end();
System.out.println("____________________________________________");
System.out.println("____________________________________________");
new facadeClient().oldMethod();//这个是不使用外观类的旧方法,可以看出用户完成一件事是非常麻烦的,需要15个步骤才可以完成一次看电影
}
}
运行结果
外观模式的优点:
- 使客户和子系统中的类无耦合,并且使子系统使用起来更加方便。
- 外观只是提供了一个更加简洁的界面,并不影响用户直接使用子系统中的类。
- 子系统中任何类对其方法的内容进行修改,不影响外观类的代码。