Logo
Section 1 / 5

使用 Web 适配器实现依赖倒置

学习如何使用 Web 适配器实现依赖倒置。

导入

使用 Web 适配器实现依赖倒置

学习如何使用 Web 适配器实现依赖倒置。

简介

如今大多数应用程序都具备某种形式的 Web 界面——要么是可以通过浏览器交互的 #key# UI:用户界面 #key#,要么是其他系统可调用以与我们的应用进行交互的 #key# HTTP:超文本传输协议 #key# #key# API:应用程序编程接口 #key#。

在我们目标架构中,所有与外界的通信都通过适配器进行。接下来我们讨论如何实现一个提供此类 Web 界面的适配器。

下图详细展示了与 Web 适配器相关的架构元素——适配器本身,以及它与应用核心交互所使用的端口。

带端口的 Web 适配器

...
传入适配器通过专用的传入端口与应用层通信,这些端口由应用服务实现。

Web 适配器是一种“驱动型”或“传入型”适配器。它接收来自外部的请求,并将其转换为对应用核心的调用,告诉核心需要执行什么操作。控制流从 Web 适配器中的控制器流向应用层中的服务。

应用层提供了特定的端口,供 Web 适配器与其通信。这些服务实现了端口接口,而 Web 适配器则通过调用这些端口来与核心交互。

如果我们进一步观察,会发现这正是依赖倒置原则(Dependency Inversion Principle)的实际体现。由于控制流是从左向右的,我们也可以让 Web 适配器直接调用用例(use cases),如下图所示。

直接调用方式

...
我们可以移除端口接口,直接调用服务。

那么,为什么要在适配器和用例之间增加一层间接层呢?原因在于,端口明确定义了外部世界可以与应用核心交互的位置。有了端口,我们就能清楚地知道哪些地方涉及外部通信,这对于维护遗留代码的工程师来说是非常有价值的信息。

尽管如此,在“有意识地走捷径”这一章节中,我们会讨论一种常见的简化做法:省略传入端口,直接调用应用服务。

我们仍需回答一个对高度交互式应用而言非常关键的问题。设想一个通过 WebSocket 向用户浏览器发送实时数据的应用程序。此时,应用核心如何将实时数据发送给 Web 适配器,再由后者转发至用户的浏览器?

Course Image

对于这种场景,我们必须引入一个端口。该端口应由 Web 适配器实现,并由应用核心调用,如下图所示。

WebSocket 场景

...
如果应用需要主动通知 Web 适配器,则必须通过传出端口,以确保依赖关系方向正确。

从技术上讲,这是一个传出端口,这意味着 Web 适配器同时扮演了传入和传出适配器的角色。但同一个适配器兼具两种角色并无矛盾之处。

在本章后续内容中,我们将默认 Web 适配器仅为传入型适配器,因为这是最常见的情况。

实现一个用例

Web适配器的职责