XiaoLin's Blog

Xiao Lin

门面设计模式学习笔记

6
2024-02-26

门面设计模式介绍

门面设计模式(Facade Design Pattern)是一种结构型设计模式,它为子系统中的一组接口提供一个一致的界面,使得这个子系统更容易使用。在门面设计模式中,有一个高层接口(门面),它封装了子系统中的多个接口,使得客户端只需要与门面进行交互,而不需要关心子系统内部的实现细节。

门面设计模式的主要优点如下:

  1. 简化接口:通过提供一个统一的接口,门面设计模式使得客户端代码更简洁、易读,降低了客户端与多个子系统进行交互的复杂性。
  2. 更好的封装:门面设计模式将子系统内部的实现细节隐藏起来,客户端无法直接访问子系统内部的接口。这有助于保护子系统的实现,使其更易于修改和维护。
  3. 灵活性:门面设计模式允许在子系统内部进行变更,而不影响客户端代码。这意味着客户端可以继续使用相同的接口,而无需关心子系统内部的实现变化。
  4. 易于扩展:门面设计模式使得在子系统内部添加新功能或修改现有功能变得更加容易,因为客户端不需要关心这些变化。

在 Java 中,门面模式通常用于以下场景:

对外提供 API:当一个系统需要对外提供 API 时,可以使用门面模式将 API 进行封装,使得客户端只需要使用一个简单的接口就可以调用系统的功能。
与其他系统进行交互:当一个系统需要与其他系统进行交互时,可以使用门面模式将与其他系统的交互进行封装,使得系统可以更容易地与其他系统进行集成。
简化复杂的操作:当一个系统需要进行复杂的操作时,可以使用门面模式将操作进行封装,使得操作可以更容易地使用和理解。
对系统进行分层:当一个系统需要进行分层时,可以使用门面模式将不同层之间的接口进行封装,使得各层之间的依赖关系更加清晰,同时也更容易进行维护和修改。

在实际应用中,门面设计模式被广泛应用于各种场景,如软件框架、数据库操作、网络通信等。例如,在 Java 开发中,Spring 框架就使用了门面设计模式,为数据库操作、事务管理、缓存等提供了统一的接口,使得开发者能够更轻松地使用这些功能。

门面模式实现

当一个系统需要与多个第三方服务进行交互时,可以使用门面模式来对这些服务进行封装,使得客户端只需要与一个门面类交互就可以完成对多个服务的调用。下面是一个简单的示例代码:

  • 暴露的复杂服务伪代码
package xyz.xiaolinz.demo.facade;

/**
 * 门面模式 - 需要组合的服务
 *
 * @author huangmuhong
 * @date 2023/11/27
 * @version 1.0.0
 *
 */
public interface EndpointService {

  /**
   * 做一点事
   *
   *
   *
   * @author huangmuhong
   * @date 2023/11/27
   * @since 1.0.0
   */
  void doSomething();

}

package xyz.xiaolinz.demo.facade;

/**
 * @author huangmuhong
 * @date 2023/11/27
 */
public class DiscoveryEndpointService implements EndpointService {

  @Override
  public void doSomething() {
    System.out.println("DiscoveryEndpointService do something");
  }
}

package xyz.xiaolinz.demo.facade;

/**
 * http端点服务
 *
 * @author huangmuhong
 * @date 2023/11/27
 * @version 1.0.0
 * @see EndpointService
 */
public class HttpEndpointService implements EndpointService {

  @Override
  public void doSomething() {
    System.out.println("HttpEndpointService do something");
  }
}

  • 门面类
package xyz.xiaolinz.demo.facade;

/**
 * 门面模式 - 门面角色
 * 提供对外的统一接口
 * 通过组合的方式,将多个服务组合在一起
 *
 * @author huangmuhong
 * @date 2023/11/27
 * @version 1.0.0
 *
 */
public class EndpointFacade {

  private final EndpointService discoveryEndpointService;

  private final EndpointService httpEndpointService;

  public EndpointFacade(EndpointService discoveryEndpointService,
      EndpointService httpEndpointService) {
    this.discoveryEndpointService = discoveryEndpointService;
    this.httpEndpointService = httpEndpointService;
  }

  public void doSomething() {
    discoveryEndpointService.doSomething();
    httpEndpointService.doSomething();
  }

}

使用场景

还要强调一下,门面模式定义中的“子系统(subsystem)”也可以有多种理解方式。它既可以是一个完整的系统,也可以是更细粒度的类或者模块。关于这一点,在下面的讲解中也会有体现。

门面模式可以让子系统更加易用,实际上,它除了解决易用性问题之外,还能解决其他很多方面的问题,如分布式事物等。

源码使用

门面模式在 JDK 源码中有很多应用。以下是一些常见的使用场景:

(1)JDBC:在 Java 中使用 JDBC 连接数据库时,通常会使用 DriverManager 来获取连接。DriverManager 就是一个门面类,它将多个数据库驱动进行封装,使得客户端只需要使用一个简单的接口就可以访问不同的数据库。

(2)Spring 框架:在 Spring 框架中,ApplicationContext 就是一个门面类,它将 Spring 中的各个组件进行封装,使得客户端可以更容易地使用 Spring 中的功能。

(3)Servlet API:在 Servlet API 中,HttpServletRequest 和 HttpServletResponse 接口就是门面类,它们将底层的网络通信进行封装,使得开发者可以更容易地编写 Web 应用程序。