继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库Java设计模式克隆下载学习使用!
5.6 外观模式
5.6.1 概述
- 又称门面模式,通过为多个子系统提供一个一致接口,而使这些子系统更加容易被访问的模式
- 对外有一个统一接口,外部应用程序不用关心内部细节
- 是“迪米特法则”典型应用
5.6.2 结构
- 外观(Facade)角色:为多个子系统对外提供共同接口
- 子系统(Sub System)角色:实现系统弄部分功能,客户接通过外观角色访问
5.6.3 案例(电器)
- 子系统
public class AirCondition {
public void on(){
System.out.println("空调已打开。");
}
public void off(){
System.out.println("空调已关闭。");
}
}
public class Light {
public void on(){
System.out.println("电灯已打开。");
}
public void off(){
System.out.println("电灯已关闭。");
}
}
public class TV {
public void on(){
System.out.println("电视已打开。");
}
public void off(){
System.out.println("电视已关闭。");
}
}
- 外观角色
public class SmartApplicationFacade {
private Light light;
private TV tv;
private AirCondition airCondition;
public SmartApplicationFacade() {
this.light = new Light();
this.tv = new TV();
this.airCondition = new AirCondition();
}
// 语音控制
public void say(String message) {
if (message.contains("打开"))
on();
else if (message.contains("关闭"))
off();
else System.out.println("我听不懂!");
}
// 一键打开功能
private void on(){
light.on();
tv.on();
airCondition.on();
}
// 一键关闭功能
private void off(){
light.off();
tv.off();
airCondition.off();
}
}
- 测试
public static void main(String[] args) {
SmartApplicationFacade smartApplicationFacade = new SmartApplicationFacade();
smartApplicationFacade.say("打开电器");
smartApplicationFacade.say("关闭电器");
}
- 结果
5.6.4 优缺点
5.6.4.1 优点
- 降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类
- 对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易
5.6.4.2 缺点
- 不符合开闭原则,修改很麻烦
5.6.5 使用场景
- 对分层结构系统构建时,使用外观模式定义子系统中每层的入口点可以简化子系统之间的依赖关系
- 当一个复杂系统的子系统很多时,外观模式可以为系统设计一个简单的接口供外界访问
- 当客户端与子系统之间存在很大的联系,引入外观模式可将它们分离,从而提高子系统的独立性
5.7.5 源码解析
Tomcat作为Web容器时,接收浏览器发送的请求,Tomcat将请求信息封装成ServletRequest对象,ServletRequest是一个接口,还有子接口HttpServletRequest,request对象也是HttpServletRequest对象的子实现类对象,即RequestFacade类对象。类图如下
使用原因:
定义RequestFacade类,分别实现ServletRequest,同时定义私有变量Request,且方法实现调用Request的实现,再将RequestFacade转为ServletRequest传给servlet的service方法。这样即使在servlet中被下转为RequestFacade,也不能访问私有成员变量对象中方法。既使用了Request,又能防止其中方法不被合理访问。