Facade design pattern
外观模式的概念、外观模式的结构、外观模式的优缺点、外观模式的使用场景、外观模式的实现示例、外观模式的源码分析
1、外观模式的概念
外观模式,为多个复杂的子系统提供一个统一的接口,使得这些子系统更加容易被访问。在现有的系统中增加一个接口,提供了客户端请求的简化方法和现有系统类方法的委托调用,同时隐藏了系统的复杂性。
2、外观模式的结构
- 子系统抽象接口: 定义子系统的行为,可有可无。
- 具体子系统:实现子系统抽象接口,实现子系统具体行为。
- 外观类:持有子系统的引用并对外提供访问系统的简化方法以及对现有子系统的委托调用。
3、外观模式的优缺点
- 优点:
- 减少系统的相互依赖。
- 提高灵活性。
- 增加安全性。
- 缺点:
- 增加子系统时可能需要修改外观类,不符合开闭原则。
4、外观模式的使用场景
- 对分层结构系统构建时,使用外观模式定义子系统中每层的入口可以简化子系统之间的依赖关系。
- 当一个复杂系统中子系统很多时,可以对外提供一个统一的访问接口。
- 当客户端与多个子系统之间存在很大的关联时,可使用外观模式将它们分离,从而提高子系统的独立性和可移植性。
5、外观模式的实现示例
子系统抽象接口:
public interface Hero {
/**
* 定义子系统行为
*/
void attack();
}
子系统一:
public class ZedHero implements Hero {
@Override
public void attack() {
System.out.println("瞬狱影杀阵");
}
}
子系统二:
public class FizzHero implements Hero {
@Override
public void attack() {
System.out.println("巨鲨来袭");
}
}
子系统三:
public class AhriHero implements Hero {
@Override
public void attack() {
System.out.println("灵魂突袭");
}
}
外观类:
public class Facade {
private Hero zed;
private Hero fizz;
private Hero ahri;
public Facade() {
this.zed = new ZedHero();
this.fizz = new FizzHero();
this.ahri = new AhriHero();
}
/**
* 对外提供的统一接口
*/
public void attack() {
this.zed.attack();
this.fizz.attack();
this.ahri.attack();
}
}
测试:
public class FacadeTest {
public static void main(String[] args) {
Facade facade = new Facade();
facade.attack();
}
}
测试结果:
瞬狱影杀阵
巨鲨来袭
灵魂突袭
6、外观模式的源码分析
使用 tomcat 作为 web 容器时,浏览器发送过来的请求,tomcat 会讲请求信息封装成 ServletRequest 对象,通过输出 request 对象发现,这里的 request 对象实际上是 HttpServletRequest 的子实现类 RequestFacade 的实例。RequestFacade 类分别实现了 ServletRequest 和 HttpServletRequest,同时持有私有成员变量 Request,并且方法的实现调用了 Request 的实现。将 RequestFacade 上转为 ServletRequest 传给 servlet 的 service 方法,这样即使在 servlet 中被下转位 RequestFacade,也不能访问私有成员变量中的方法,既用了 Request,又能防止其中的方法被哪非法访问。