跳至主要內容

门面模式

AruNi_Lu设计模式设计模式与范式约 1445 字大约 5 分钟

本文内容

前言

我们平时在开发接口的时候,一个常见的问题就是 接口粒度 的问题。

为了保证接口的 可复用性(或叫通用性),我们需要把接口设计得 细粒度一点,职责单一一点。但这样又会导致调用者在使用时需要调用 n 多个细粒度的接口,才能完成某个功能,这称为接口的易用性不好。

而如果 接口的粒度设计得过大,一个接口要做 n 多件事情,返回 n 多个数据,就会导致接口 不够通用、可复用性不好

那如何解决接口的 可复用性和易用性之间的矛盾 呢?这就要谈到我们本章的 门面模式 了。

1. 什么是门面模式

门面模式,也叫做外观模式,它的定义是:门面模式为子系统提供一组统一的接口,定义一组高层接口让子系统更易用

举个例子,假设有一个系统 A,提供了 func1、func2、func3、func4 四个接口,系统 B 要完成某个功能,需要调用 A 系统的 func1、func2、func4 接口。

那么我们就可以利用 门面模式,提供一个 包裹 func1、func2、func4 接口调用的门面接口 func124,给系统 B 直接使用。

你可能会有疑问,如果外部需要调用的接口都各不相同,那就要为它们都提供一个门面接口吗?

这显然不是的,这样就要定义很多的接口,显然是不合理的。

所以我们应该根据实际情况来使用门面模式,有些情况可以直接让外部依次调用我们提供的接口,有些情况则需要提供门面接口。

这就涉及到门面模式的应用场景了,下面就具体来讲讲。

2. 应用场景

在门面模式的定义中说到 “门面模式让子系统更易用”,实际上,门面模式除了解决易用性问题之外,还能解决其他很多方面的问题,也就是它的应用场景。

2.1 解决易用性问题

门面模式封装了系统的底层实现、隐藏了系统的复杂性,提供了一组更加简单易用、更高层的接口

例如,Linux 系统的调用函数就可以看作一种门面,它是 Linux 系统暴漏给开发者使用的一组特殊的编程接口,它封装了低层更基础的 Linux 内核调用,使得开发者在使用时更加简单、易用。

再例如,Linux 的 Shell 命令也可以看作一种门面,它也封装了系统调用,提供了更加友好、简单的命令,让开发者可以直接通过命令与操作系统交互。

不知道你有没有发现,其实门面模式在解决易用性问题上,很像封装、抽象的设计思想,它提供更抽象的接口,封装了低层的实现细节。也很像迪米特法则(有依赖关系的类之间,只依赖必要的接口)和接口隔离原则(只为使用者提供与之有关的接口,不强迫使用者依赖它不需要的接口)。所以其实这些 设计原则、思想、模式很多都是相通的,都是为了解决系统的易用性、复用性、扩展性、维护性等问题

2.2 解决性能问题

如果我们的接口需要使用 网络通信 来进行请求,比如 RPC,而且外部系统在调用接口时,需要调用多个接口 才能完成某个功能,此时就需要进行多次接口调用,消耗多次网络通信的时间。所以,利用 门面模式,就可以将这多个接口包裹成一个门面接口,这样外部在调用时就只需要 进行一次网络通信,大大提高了响应速度。

那么在实现的时候,应该如何组织门面接口和非门面接口呢?

这可以根据门面接口的数量来决定:

  • 门面接口不多,那就可以将它跟非门面接口放到一块,当作普通接口来用即可;
  • 门面接口很多,那就可以在已有的接口之上,再抽象出一层专门放置门面接口的类或包,从类、包的命名上跟原来的接口层做区分;
  • 如果门面接口特别多,并且很多都是跨多个子系统的,那就可以将门面接口放到一个新的子系统中。

3. 总结

我们通过接口粒度的设计,引申到门面模式。接口粒度设计得过大会导致接口复用性不好、过小又会导致接口易用性不好。所以在实际开发中,需要权衡好这两方面。

我们要 尽量保持接口的可复用性,针对特殊的情况,可以使用冗余的门面接口,来提高更易用的接口

门面模式除了解决易用性问题之外, 还能在进行网络通信的接口请求中 提高性能(接口响应速度)。

上次编辑于: