简介
1.外观模式(Facade) 也叫"过程模式":外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口.这个接口使得这一子系统更加容易使用
2.外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需要跟这个接口发生调用,,而不需关心这个子系统内部的调用细节
外观模式的原理图
1.外观类(Facade):为调用端提供统一的调用接口,外观类知道了那些子系统负责处理请求,从而将调用端的请求代理给适当的子系统对象
案例 影院管理项目
2.调用者(Client).外观接口调用者
3.子系统的集合:指的是模块或者子系统,处理Facede对象指派的任务,它是功能的提供者
组建一个家庭影院 : DVD播放器,投影仪,自动屏幕.环绕立体声,爆米花机,要求完成家庭影院的功能,其过程为:
1.直接使用遥控器:统筹设备开关
2.开爆米花机
3.放下屏幕
4.开投影仪
5.开音响
6.开DVD,选dvd
7.去拿爆米花
8.调暗灯光
9.播放
10.观影结束之后,关闭各种设备
传统方式解决
1.创建所有的类
2,创建对象
3.调用方方法
.....
传统方式解决影院管理问题分析
1.在ClientTest的main方法中.创建各个子系统的对象,并且直接去调用子系统(对象)的相关方法,或造成调用过程混乱,没有清晰的过程
2.不利于ClientTest中,去维护子系统的操作
3.解决思路,定义一个高层接口,给子系统中的一组接口提供一个一致的界面(比如在高层接口提供的四个方法ready.play,pause,end)用来访问子系统中的一群接口
4.也就是说,通过定义一个一致的接口(界面类).用以屏蔽内部子系统的细节,使得调用端只需要跟这个接口发生调用,而无需关心这个子系统的内部细节 ==>> 外观模式
解决方案
1.外观模式可以理解为转换一群接口,客户只要调用一个接口,而不用调用多个接口才能实现目的,比如再pc上安装软件的时候,经常以后一键安装,可以省区很多操作
2.外观模式就是解决多个复杂接口带来的使用困难,起到简化用户操作的作用
实例
1.类图
2.代码
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 play ");
}
public void pause() {
System.out.println(" dvd pause ");
}
}
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 pop ");
}
}
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 focus ");
}
}
public class Screen {
private static Screen instance = new Screen();
public static Screen getInstance() {
return instance;
}
public void up() {
System.out.println(" Screen up ");
}
public void down() {
System.out.println(" Screen down ");
}
}
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(" Stereo up ");
}
public void down() {
System.out.println(" Stereo down ");
}
}
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 up() {
System.out.println(" TheaterLight up ");
}
public void down() {
System.out.println(" TheaterLight` down ");
}
}
public class HomeClient {
// 定义各个子系统对象
private TheaterLight light;
private DVDPlayer dvdPlayer;
private Popcorn popcorn;
private Screen screen;
private Stereo stereo;
private Projector projector;
public HomeClient() {
this.light = light.getInstance();
this.dvdPlayer = dvdPlayer.getInstance();
this.popcorn = popcorn.getInstance();
this.screen = screen.getInstance();
this.stereo = stereo.getInstance();
this.projector = projector.getInstance();
}
// 操作分为4步骤
public void ready() {
popcorn.on();
popcorn.pop();
screen.down();
projector.on();
stereo.on();
dvdPlayer.on();
light.down();
}
public void play() {
dvdPlayer.play();
}
public void pause() {
dvdPlayer.pause();
}
public void end() {
popcorn.off();
popcorn.off();;
screen.up();
projector.off();
stereo.down();
dvdPlayer.off();
light.up();
}
}
测试
public class Client {
public static void main(String[] args) {
HomeClient client = new HomeClient();
System.out.println("--------------------");
client.ready();
System.out.println("--------------------");
client.play();
System.out.println("--------------------");
client.pause();
System.out.println("--------------------");
client.end();
}
}
打印结果
--------------------
Popcorn on
Popcorn pop
Screen down
Projector on
Stereo on
dvd on
TheaterLight` down
--------------------
dvd play
--------------------
dvd pause
--------------------
Popcorn off
Popcorn off
Screen up
Projector off
Stereo down
dvd off
TheaterLight up
外观模式再Mybatis框架应用得源码分析
1.类图
2.Mybatis中的 Configuration 去创建 Meta Object对象使用到了外观模式
public MetaObject newMetaObject(Object object) {
return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
if (object == null) {
return SystemMetaObject.NULL_META_OBJECT;
} else {
return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
}
外观模式的注意事项和细节
1.外观模式对外屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复杂度
2.外观模式对客户端和子系统的耦合关系,使得子系统内部的模块更容易维护和多站
3.通过合理的使用外观模式,可以使得我们更好的划分访问的层次
4.当系统需要分层设计的时候,可以考虑使用Facade模式
5.在维护一个遗留的大型系统的时候,可能这个系统已经非常难以维护和拓展,此时可以考虑为新系统设计一个 Facade类,来提供遗留系统比较清晰的简单接口,当新系统一个Facade类交互,提高复用性
6.不能过多或者不合理的使用外观模式,使用外观模式好,还是直接调用好,要让系统有层次,利于维护为目的