一、了解外观模式
1.1 什么是外观模式
外观模式 (Facade Pattern) 提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
想要使用外观模式,我们需要创建一个接口来简化和统一包装一个子系统的一个或多个类。外观模式允许我们让客户和子系统之间避免紧耦合。
1.2 外观模式的组成结构
- 客户 (Client):通过调用 Facede 来完成要实现的功能。
- 外观 (Facade):外观模式的核心。它被客户角色调用,它熟悉子系统的功能。内部根据客户角色的需求预定了几种功能的组合。
- 复杂的子系统:实现了子系统的功能。它对客户角色和 Facade 是未知的。它内部可以有系统内的相互交互,也可以由供外界调用的接口。
1.3 外观模式 UML 图解
1.4 外观模式适用场景
- 设计初期阶段,应该有意识的将不同层分离,层与层之间建立外观模式。
- 开发阶段,子系统越来越复杂,增加外观模式提供一个简单的调用接口。
- 维护一个大型遗留系统的时候,可能这个系统已经非常难以维护和扩展,但又包含非常重要的功能,为其开发一个外观类,以便新系统与其交互。
二、外观模式具体应用
2.1 问题描述
看电影:大部分人应该都喜欢看电影,我们来想一下我们去电影院看电影,从坐下座位后都是需要哪些步骤。首先在电影没有正式放映之前会先放一会儿广告;然后将灯光调暗;接着后台播放器播放对应的 DVD,电影正式播放;当电影播放完毕后就是将灯光调回明亮;关闭播放器。
2.2 伪代码模拟过程
ads.on(); // 电影未开始之前,放映一会儿广告
ads.close(); // 电影快开始时,关闭广告
light.dim(10); // 将灯光的亮度调到 10%
dvdPlayer.on(dvd); // 播放器播放对应的 DVD
light.dim(100); // 电影结束后,将灯光亮度调到 100%
dvdPlayer.close(); // 关闭播放器
上面这种方式,用代码模拟电影院的步骤变得很复杂。我们可以使用外观模式,把这些复杂的步骤封装起来,只对外提供简单的方法。
2.3 外观模式设计图
2.4 外观模式代码实现
子系统广告 Advertisement 类
package com.jas.facade;
public class Advertisement {
void on(){
System.out.println("现在开始播放广告,电影即将开始播放!");
}
void close(){
System.out.println("广告播放结束!");
}
}
子系统灯光 Light 类
package com.jas.facade;
public class Light {
void dim(int brightness){
System.out.println("调整灯光亮度为:" + brightness + "%!");
}
}
子系统播放器 DVDPlayer 类
package com.jas.facade;
public class DVDPlayer {
void on(String dvd){
System.out.println("现在开始播放电影,观看的电影是" + dvd + "!");
}
void close(){
System.out.println("电影播放结束,请大家按秩序退场,关闭播放器!");
}
}
外观 TheaterFacade 类
package com.jas.facade;
public class TheaterFacade {
Advertisement ads;
Light light;
DVDPlayer dvdPlayer;
public TheaterFacade(Advertisement ads, Light light, DVDPlayer dvdPlayer){
this.ads = ads;
this.light = light;
this.dvdPlayer = dvdPlayer;
}
void watchMovie(String dvd){
ads.on();
ads.close();
light.dim(10);
dvdPlayer.on(dvd);
}
void endMovie(){
light.dim(100);
dvdPlayer.close();
}
}
客户类
package com.jas.facade;
public class TheaterTestDrive {
public static void main(String[] args) {
Advertisement ads = new Advertisement();
Light light = new Light();
DVDPlayer dvdPlayer = new DVDPlayer();
TheaterFacade facade = new TheaterFacade(ads, light, dvdPlayer);
facade.watchMovie("复仇者联盟×");
facade.endMovie();
}
}
/**
* 输出
* 现在开始播放广告,电影即将开始播放!
* 广告播放结束!
* 调整灯光亮度为:10%!
* 现在开始播放电影,观看的电影是复仇者联盟×!
* 调整灯光亮度为:100%!
* 电影播放结束,请大家按秩序退场,关闭播放器!
*/
三、 外观模式总结
3.1 外观模式优点
- 实现了子系统与客户端之间的松耦合关系。
- 客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易。
3.2 外观模式知识点总结
- 当需要简化并统一一个很大的接口或者一个复杂的接口时,可以使用外观。
- 外观将客户从一个复杂的子系统中解耦。
- 实现一个外观,需要将子系统组合进外观中,然后具体的工作委托给子系统执行。
PS:点击了解更多设计模式 http://blog.csdn.net/codejas/article/details/79236013
参考文献
《Head First 设计模式》