1. 定义
门面模式(外观模式):为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
现实中的场景,比如网页的导航、应用的菜单等,屏蔽了功能的复杂交互,是门面模式的体现。
一个系统功能复杂且庞大,组件之间依赖网状结构。当其他系统要调用的时候,因为各个子系统复杂的关系网,导致调用的过程变得复杂和难以维护,一旦某个子系统做出调整,所有的客户端调用均要跟着做调整。
门面模式为了解决网状依赖对客户端调用带来的不方便,在客户端和子系统的调用接口之间,再抽象出一个层次出来,由这个层来管理子系统间复杂的调用关系,然后暴露出简单的接口提供给客户端,降低整体系统调用的复杂度。
未来子系统有变化了,客户端无需修改。
应用门面模式后整体拓扑结构的变化如下:
门面模式2. 设计
主要角色:
- 门面,定义和使用者交互的接口,将会调用子系统或者传递给子系统处理。
- 子系统,具体的业务,一个系统会有多个子系统。
类图如下:
门面模式-类图3. 应用
主要应用在这样的场景:
- 存在有多个子系统,之间的调用关系和依赖关系复杂。
- 系统解耦,把客户端和子系统进行解耦,各自独立变化。
- 中心化操作,能够对所有子系统进行管理和监控。
- 隐藏细节,不准备暴露过多子系统的实现给客户端,调整子系统实现不会影响到客户端。
- 系统兼容,如果有多套系统要进行合并输出统一的能力,又不准备修改系统的原有设计,通过抽象的 Facade 层来统一接口,进行打通。
3.1. Spring 的 ApplicationContext
ApplicationContext 作为整个应用上下文,对外屏蔽了整个 Spring 框架的内部实现,只暴露出简单的接口供外界使用。
比如从加载文件到从 Bean 容器中把 Bean 读取出来,只需要简单的接口调用。
ApplicationContext context = new ClassPathXmlApplicationContext("hello.xml");
HelloWorld helloWorld = context.getBean(HelloWorld.class);
helloWorld.say();
而内部的实现非常复杂,比如:
- 使用 ResourceLoader 读取配置文件。
- 使用 BeanDefinitionReader 解析配置文件,获取 Bean 定义信息。
- 使用 BeanDefinitionRegistry 注册解析后的 Bean 定义,进行保存。
- 使用 BeanFactory 实例化和进行依赖注入。
整个流程是多个子系统配合完成的。
但对于调用者来说,只看到 ApplicationContext 提供简单接口,内部复杂的实现流程对于客户端透明。
3.2. 其他
- 项目的 facade 层设计
4. 特点
4.1. 优势
- 解耦,子系统和客户端解耦,两者独立变化。客户端和子系统的修改互不影响。
- 易使用,客户端面向门面类编程,无需关心子系统的复杂关系,代码变得简单。
4.2. 缺点
- 新增子系统可能需要更改到外观类的源码。
- 灵活性降低,无法直接访问子系统。
网友评论