门面模式(外观模式)——屏蔽子系统的复杂性


Demo 地址: https://github.com/ooblee/HelloDesignPattern

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. 缺点

  • 新增子系统可能需要更改到外观类的源码。
  • 灵活性降低,无法直接访问子系统。
发布了61 篇原创文章 · 获赞 43 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/firefile/article/details/90314072