设计模式-Facade

结构型模式

组成

门面模式/外观模式(Facade Pattern)通过定义了一个高层次的接口,为子系统中的一组接口提供一个一致的界面,使得这个子系统更加容易使用。

屏蔽子系统一些复杂的内部行为

门面模式最重要的是创建一个门面类,该门面类对外代表了一个子系统,如下图所示:

上图中的参与者有:

  • Facade:把客户的请求转发给子系统中的某个对象;
  • 子系统:提供功能的子系统,没有 Facade 的任何信息,不持有 Facade 的引用。

在上图中,如果没有 Facade 类,那么 Client 在与子系统交互时,需要依赖子系统中的所有对象,增加了系统的复杂程度。通过引入一个 Facade 对象,它为子系统提供一个单一而简单的界面,这样 Client 只需要依赖 Facade 对象即可。

应用场景

当存在以下情况时,推荐使用 门面模式:

  • 当我们要为一个复杂子系统提供一个简单的接口时,Facade 对象提供一些基本的方法,以满足常规的需求;如果需要使用更复杂功能的场景,也可以直接绕过 Facade 使用子系统中的对象。
  • 当我们需要构建一个分层的系统时,使用 Facade 模式定义每一层系统的入口;如果同一层的子系统之间相互依赖,可以让它们通过 Facade 进行通信,简化它们的依赖关系。

微服务架构中的一个服务,可以看作是一个子系统,它对外提供的的SDK可以看作这个服务的 Facade 对象。

示例代码

tomcat 给 Request 类提供一个 Facade 类:RequestFacade,用来屏蔽 Request 的复杂操作,也避免用户受到非 servlet 标准方法的干扰。

RequestFacade 与 Request 的 UML 如下图所示:

当我们在 Spring 容器或者接口中调用 HttpServletRequest 时,实际调用的是 RequestFacade 对象。当我们调用它的方法时,都会转发给对应的 Request request 对象。

示例代码如下:

java 复制代码
/**
 * The wrapped request.
 */
protected Request request = null;

public RequestFacade(Request request) {

    this.request = request;
}

@Override
public Object getAttribute(String name) {

    if (request == null) {
        throw new IllegalStateException(
            sm.getString("requestFacade.nullRequest"));
    }

    return request.getAttribute(name);
}

这里需要注意的是,RequestFacade 和 Request 都实现了 HttpServletRequest 接口,并且 RequestFacade 持有 Request 对象,也就是说 Facade 继承了要屏蔽的对象。

其实一般是不用这么做的,这里之所以这么做,是因为服务中后续对 Request 的操作都是在操作 HttpServletRequest 对象,所以这里 RequestFacade 才要实现 HttpServletRequest,否则无法继续向下继续传递。

优点和缺点

门面模式的优点:

  • 因为减少了客户端需要依赖的子系统对象,使得子系统使用起来更加方便;
  • 实现了子系统与客户之间的松耦合关系,使得子系统内部的变化不会影响到客户端;
  • Facade 模式有助于建立层次结构系统,有助于对象之间的依赖关系分层;
  • Facade 不限制客户端使用子系统中的对象,具有很大的选择灵活性;

小结

Facade 模式可以为一个子系统提供统一的简单界面,降低客户端与子系统之间的耦合。

Facade 和 Proxy 看上去有些相似,但是两者是有很大区别的:

  • Proxy 是代理某个对象,给被代理对象增加一些非逻辑的功能
  • Facade 是作为一个子系统的"门面",不会增加功能,而是屏蔽复杂性,请求是被直接转发到子系统的
相关推荐
盖世英雄酱581361 小时前
Java 组长年终总结:靠 AI 提效 50%,25 年搞副业只赚 4k?
后端·程序员·trae
+VX:Fegn08951 小时前
计算机毕业设计|基于springboot + vue在线音乐播放系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
code bean2 小时前
Flask图片服务在不同网络接口下的路径解析问题及解决方案
后端·python·flask
+VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue律师咨询系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
努力的小郑2 小时前
2025年度总结:当我在 Cursor 里敲下 Tab 的那一刻,我知道时代变了
前端·后端·ai编程
颜淡慕潇4 小时前
深度解析官方 Spring Boot 稳定版本及 JDK 配套策略
java·后端·架构
Victor3564 小时前
Hibernate(28)Hibernate的级联操作是什么?
后端
Victor3564 小时前
Hibernate(27)Hibernate的查询策略是什么?
后端
superman超哥4 小时前
Rust 内部可变性模式:突破借用规则的受控机制
开发语言·后端·rust·rust内部可变性·借用规则·受控机制
柒.梧.5 小时前
Spring核心知识全解析:从入门实战到进阶
java·后端·spring