基本需求:
- 组建一个家庭影院:DVD 播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的功能,
- 其过程为:直接用遥控器:统筹各设备开关
- 开爆米花机、放下屏幕、开投影仪、开音响、开 DVD,选 dvd、去拿爆米花、调暗灯光、播放、观影结束后,关闭各种设备
传统方案:
- 客户端直接依赖各种设备,直接调用各种设备的方法
- UML类图
- 在Client中,创建各个子系统的对象,并直接去调用子系统(对象)相关方法,会造成调用过程混乱,没有清晰的过程,不利于维护
- 定义一个高层接口,给子系统中的一组接口提供一个一致的界面(比如在高层接口提供四个方法ready,play,pause,end),用来访问子系统中的一群接口,就是通过定义一个一致的接口(界面类),用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节 -> 外观模式
基本介绍:
-
外观模式(Facade)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用
-
为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
-
主要解决:降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口
-
UMl类图(原理)

- Facade类为外观类,聚合了其他多个子系统(实际功能的提供者),让client统一调用
-
UML类图(案例)
-
代码实现
-
public class DVDPlayer {
// DVD播放器 使用饿汉
public static final DVDPlayer DVD_PLAYER = new DVDPlayer();
private DVDPlayer() {
}
public static DVDPlayer getInstance() {
return DVD_PLAYER;
}
public void on() {
System.out.println("dvd on");
}
public void off() {
System.out.println("dvd off");
}
public void play() {
System.out.println("dvd play");
}
public void pause() {
System.out.println("dvd pause");
}
}
-
public class Screen {
// 屏幕 使用饿汉
public static final Screen SCREEN = new Screen();
private Screen() {
}
public static Screen getInstance() {
return SCREEN;
}
public void up() {
System.out.println("screen up");
}
public void dowm() {
System.out.println("screen down");
}
}
-
public class Popcorn {
// 爆米花机 使用饿汉
public static final Popcorn POPCORN = new Popcorn();
private Popcorn() {
}
public static Popcorn getInstance() {
return POPCORN;
}
public void on() {
System.out.println("popcorn on");
}
public void off() {
System.out.println("popcorn off");
}
public void pop() {
System.out.println("popcorn pop");
}
}
-
public class Projector {
// 投影仪 使用饿汉
public static final Projector PROJECTOR = new Projector();
private Projector() {
}
public static Projector getInstance() {
return PROJECTOR;
}
public void on() {
System.out.println("projector on");
}
public void off() {
System.out.println("projector off");
}
public void focus() {
System.out.println("projector focus");
}
}
-
public class TheaterLight {
// 影院灯光 使用饿汉
public static final TheaterLight THEATER_LIGHT = new TheaterLight();
private TheaterLight() {
}
public static TheaterLight getInstance() {
return THEATER_LIGHT;
}
public void on() {
System.out.println("theater_light on");
}
public void off() {
System.out.println("theater_light off");
}
public void dim() {
System.out.println("theater_light dim");
}
public void bright() {
System.out.println("theater_light bright");
}
}
-
public class Stereo {
// 立体声 使用饿汉
public static final Stereo STEREO = new Stereo();
private Stereo() {
}
public static Stereo getInstance() {
return STEREO;
}
public void on() {
System.out.println("stereo on");
}
public void off() {
System.out.println("stereo off");
}
public void up() {
System.out.println("stereo up");
}
}
-
public class HomeTheaterFacade {
// 影院外观类,聚合其他子系统 ,提供统一的方法供Client调用
private DVDPlayer dvdPlayer = DVDPlayer.getInstance();
private Screen screen = Screen.getInstance();
private Popcorn popcorn = Popcorn.getInstance();
private Projector projector = Projector.getInstance();
private TheaterLight theaterLight = TheaterLight.getInstance();
private Stereo stereo = Stereo.getInstance();
public HomeTheaterFacade() {
}
// 给Client提供的方法相当于子系统方法的集合
public void ready() {
popcorn.on();
popcorn.pop();
screen.dowm();
projector.on();
projector.focus();
theaterLight.on();
stereo.on();
dvdPlayer.on();
}
public void play() {
theaterLight.dim();
stereo.up();
dvdPlayer.play();
}
public void pause() {
dvdPlayer.pause();
}
public void end() {
popcorn.off();
screen.up();
projector.off();
theaterLight.off();
stereo.off();
dvdPlayer.off();
}
}
-
public class Client {
public static void main(String[] args) {
HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();
System.out.println("-----------ready-----------");
homeTheaterFacade.ready();
System.out.println("-----------play-----------");
homeTheaterFacade.play();
System.out.println("-----------pause-----------");
homeTheaterFacade.pause();
System.out.println("-----------end-----------");
homeTheaterFacade.end();
}
}
mybatis源码:
- 在mybatis的configuration类中的newMetaObject方法中创建MetaObject时使用的构造方法中就用到的外观模式
- UML类图

- configuration类就相当于facade类
注意事项:
- 外观模式对外屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复杂性
- 外观模式对客户端与子系统的耦合关系 - 解耦,让子系统内部的模块更易维护和扩展
- 通过合理的使用外观模式,可以帮我们更好的划分访问的
- 当系统需要进行分层设计时,可以考虑使用Facade模式(三层架构)
- 在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个Facade类,来提供遗留系统的比较清晰简单的接口,让新系统与Facade类交互,提高复用性
- 不能过多的或者不合理的使用外观模式,使用外观模式好,还是直接调用模块好。要以让系统有层次,利于维护为目的
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|