Gateway(网关)模式在 Java 设计模式中的实现:以统一接口集成外部服务(java-design-patterns 仓库详解)
示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载本技术指南以 java-design-patterns 仓库中 gateway 模块及其 西班牙语本地化版本为骨架系统讲解 Gateway 设计模式的核心思想、代码实现与适用场景。你将看到如何用一个极简的Gateway接口把多个外部服务统一封装如何通过GatewayFactory注册与按需获取网关实例以及该模式与 Facade、Adapter、Proxy、API Gateway 等模式的异同。读完即可在本仓库的源码与测试佐证下独立复现并评估这一模式。模式意图为外部系统提供统一、简化的访问接口Gateway 是一种结构型Structural设计模式其核心意图是为应用内部提供一套统一、简单的视图去访问一组外部系统或外部功能参见 gateway 模块英文 README 的 Intent 一节。它把内部系统与外部资源之间的交互封装起来屏蔽协议翻译、数据格式转换、路由分发等细节从而保证内外组件之间的松散耦合Decoupling提升应用的可维护性与可扩展性。正如 gateway 模块的西班牙语文档 所概括的目的为访问一组外部系统或功能提供入口接口Gateway 为应用的内部资源提供对外部资源的简单、统一视图。一句话总结网关可以提供一个接口让内部系统能够使用外部服务。从源码角度看App.java 的类注释 明确描述了该模式在本仓库中的落地形态创建一个Gateway接口作为与多个服务交互的公共入口并为不同外部服务提供该接口的具体实现GatewayFactory是工厂类ExternalServiceA/B/C是外部服务的模拟实现App是应用入口通过Gateway接口以远低于直接调用的复杂度去调用各个服务。现实类比城门、物流公司与 API 前端城门口的比喻Gateway 就像一座真实城市的大门。城内的居民是内部系统城外不同的城市是外部服务。城门的作用就是为内部系统提供通往不同外部服务的访问通道。—— 西语文档 Real World Example内部系统只需要认识城门这一个出入口而不需要分别了解每座外部城市的道路、语言与规则。物流公司的例子英文版 README 给出了更贴近企业级应用的场景见 gateway/README.md 的 Real-World Example一家物流公司同时使用多家第三方服务运输、库存管理、客户通知。每个服务都有自己的 API、协议和数据格式。若直接让内部系统逐一对接耦合度极高。引入 Gateway 后所有第三方交互都汇聚到一个统一接口上网关负责协议翻译、数据转换与请求路由内部系统与每个外部服务的具体实现细节彻底解耦同时对外通信有了单一控制点可维护性与可扩展性都随之改善。维基百科的定义网关是一台充当 API 前端的服务器接收 API 请求执行限流throttling与安全策略将请求转发给后端服务再把响应返回给请求方。—— 西语文档 Wikipedia 引述这个定义点出了网关在现实基础设施中的关键职责统一入口 策略执行限流、安全 请求转发/响应回传。架构概览类图下面是该模式在本仓库中的类图来源于 gateway/etc/gateway.urm.puml渲染图为 gateway.urm.png原文档亦引用此图从类图可以看出整个模式只有四类角色Gateway—— 服务接口统一契约ExternalServiceA/B/C—— 外部服务的具体实现GatewayFactory—— 网关注册表/工厂按 key 管理网关实例App—— 客户端入口只依赖Gateway接口编程。编程示例从接口到应用入口的完整链路本仓库 gateway/src/main/java/com/iluwatar/gateway 目录下共 6 个源文件完整对应上述四类角色。下面按依赖层次逐层展开。第一步定义统一契约Gateway接口Gateway.java 是全部外部服务必须遵循的契约其极其简单正是该模式的精髓——把复杂性全部收敛到实现内部/** Service interface. */ interface Gateway { void execute() throws Exception; }execute()是唯一的方法所有需要接入的外部能力最终都落到这一入口上。声明抛出Exception为服务实现保留了向调用方上报错误的空间比如网络异常、服务不可用。第二步实现外部服务三个外部服务实现类都位于同一包内均实现Gateway接口用Thread.sleep(1000)模拟耗时的外部调用用 SLF4J 记录日志Slf4j由 Lombok 生成LOGGERExternalServiceA.java/** ExternalServiceA is one of external services. */ Slf4j class ExternalServiceA implements Gateway { Override public void execute() throws Exception { LOGGER.info(Executing Service A); // Simulate a time-consuming task Thread.sleep(1000); } }ExternalServiceB.java 与 A 完全同构日志改为 Executing Service B而 ExternalServiceC.java 额外带了一个error()方法用于模拟异常场景/** ExternalServiceC is one of external services. */ Slf4j class ExternalServiceC implements Gateway { Override public void execute() throws Exception { LOGGER.info(Executing Service C); // Simulate a time-consuming task Thread.sleep(1000); } public void error() { // Simulate an exception throw new RuntimeException(Service C encountered an error); } }值得注意的是execute()是接口契约内的方法而error()是ExternalServiceC特有的扩展行为并不属于Gateway契约——这恰好演示了接口只暴露最小公共能力、具体服务的专属能力留在实现内部的设计取向。第三步用GatewayFactory管理网关注册表GatewayFactory.java 是整个模式的注册中心内部持有一个MapString, Gateway提供注册与按 key 获取两个方法public class GatewayFactory { private MapString, Gateway gateways new HashMap(); public void registerGateway(String key, Gateway gateway) { gateways.put(key, gateway); } public Gateway getGateway(String key) { return gateways.get(key); } }registerGateway(String key, Gateway gateway)把实现实例与业务 key如ServiceA绑定写入HashMapgetGateway(String key)按 key 取出网关实例若 key 不存在HashMap.get返回null测试中对此有明确断言见下文。这里的注册表模式让新增一个外部服务的成本降到最低注册新 key 即可客户端代码无需改动。第四步App入口——客户端如何消费App.java 是演示入口同时也是 pom.xml 中maven-assembly-plugin配置的可执行主类Slf4j public class App { /** Simulate an application calling external services. */ public static void main(String[] args) throws Exception { GatewayFactory gatewayFactory new GatewayFactory(); // Register different gateways gatewayFactory.registerGateway(ServiceA, new ExternalServiceA()); gatewayFactory.registerGateway(ServiceB, new ExternalServiceB()); gatewayFactory.registerGateway(ServiceC, new ExternalServiceC()); // Use an executor service for execution Gateway serviceA gatewayFactory.getGateway(ServiceA); Gateway serviceB gatewayFactory.getGateway(ServiceB); Gateway serviceC gatewayFactory.getGateway(ServiceC); // Execute external services try { serviceA.execute(); serviceB.execute(); serviceC.execute(); } catch (ThreadDeath e) { LOGGER.info(Interrupted! e); throw e; } } }调用链清晰可循注册 → 按 key 获取Gateway引用 → 通过统一接口execute()执行。客户端自始至终只与Gateway接口和GatewayFactory打交道对三个服务的具体实现零感知——这正是降低耦合、易于维护和扩展的直观体现。运行与输出按照上述代码运行后控制台输出如下西语文档 与英文 README 均给出Executing Service A Executing Service B Executing Service C英文 README 中给出了更完整的日志形态gateway/README.md 的 Running the example可以看到三个服务串行执行、各间隔约 1 秒对应各自Thread.sleep(1000)09:24:44.030 [main] INFO com.iluwatar.gateway.ExternalServiceA -- Executing Service A 09:24:45.038 [main] INFO com.iluwatar.gateway.ExternalServiceB -- Executing Service B 09:24:46.043 [main] INFO com.iluwatar.gateway.ExternalServiceC -- Executing Service C时序图一次调用如何穿过网关英文 README 提供了本模块的时序图渲染图 gateway-sequence-diagram.png源码 gateway-sequence-diagram.puml时序图直观呈现了客户端 → 工厂取实例 → 统一接口执行的消息流转是理解该模式运行时行为的辅助材料。何时使用 Gateway 模式综合 西语文档的 Aplicabilidad 与 英文 README 的 When to Use以下场景适合引入 Gateway需要访问聚合对象/外部能力而不暴露其内部表示时与多个外部服务或 API 集成时需要一个统一的访问门面需要为遍历/调用不同聚合结构提供统一接口时在微服务架构中需要通过良好定义的接口管理服务间通信时这是 Gateway 模式尤其受益的场景。真实应用场景与相关模式现实中的落地形态英文 README 的 Real-World Applicationsgateway/README.md给出两类典型形态微服务中的 API 网关作为中介处理来自客户端的请求将其路由到微服务架构中合适的服务。本仓库有专门的 microservices-api-gateway 模块 演示这一形态可视为 Gateway 模式在请求路由维度上的特化数据库网关为访问不同数据库系统提供统一接口隐藏各类数据库查询与数据检索的细节。此外与后端专用前端Backends for Frontends的思想也高度相关可参考仓库中的 backends-for-frontends 模块。与相近模式的辨析英文 README 的 Related Java Design Patternsgateway/README.md给出了精确的边界Facade 模式两者都用于抽象复杂子系统但Gateway 专门面向外部/远程接口Facade 更侧重于本地子系统Adapter 模式两者都向子系统提供不同接口但Gateway 更聚焦于网络化数据源与服务Proxy 模式两者常配合使用都能控制并管理对另一个对象的访问但Gateway 特指对外部服务的访问API Gateway常被视为 Gateway 模式的特化专门管理 API 请求并将其路由到后端系统的对应服务。收益与权衡收益Benefits将外部 API 与服务的细节抽象到更简单的接口之后显著降低系统复杂度促进应用与其外部依赖之间的松散耦合由于依赖被统一收敛系统更易于测试和维护。代价Trade-offs引入额外的一层可能对性能产生潜在影响多一跳转发需要审慎设计避免形成单体网关而成为性能瓶颈或单点故障源。测试与工程质量测试用例如何验证模式行为ServiceFactoryTest.java 用 JUnit 5 覆盖了工厂的核心行为可从测试角度印证模式的设计契约testGatewayFactoryRegistrationAndRetrieval注册后按 key 获取断言返回实例的类型分别为ExternalServiceA/B/C——验证注册-取回链路的正确性testGatewayFactoryRegistrationWithNonExistingKey对不存在的 keyNonExistingService调用getGateway断言返回null——明确了工厂对未知 key 的语义testGatewayFactoryConcurrency用固定线程池Executors.newFixedThreadPool(2)提交 10 个并发任务通过CountDownLatch同步等待断言并发执行execute()不失败——验证HashMap注册表在只读并发访问下的可用性注册在启动阶段完成、运行期只读。此外 AppTest.java 负责对演示入口做冒烟级验证。这些测试共同构成了该模式可运行、可回归的证据链。如何运行本模块示例本模块是独立 Maven 工程artifactId为gatewaypom.xml父工程为com.iluwatar:java-design-patterns依赖slf4j-api与logback-classic提供日志能力测试依赖junit-jupiter-engine。从仓库根目录可执行./mvnw -pl gateway -am package构建产物为可执行 JARmaven-assembly-plugin已将 主类com.iluwatar.gateway.App写入 manifest运行java -jar gateway/target/gateway-*.jar即可看到Executing Service A/B/C的串行输出。测试可单独执行./mvnw -pl gateway test进一步阅读Gateway 模式英文 README更详尽的意图、时序图、权衡与相关模式Gateway 模式西班牙语本地化文档本指南的主体骨架API Gateway 微服务示例Backends for Frontends 模式示例相关模式对照Facade、Adapter、Proxy说明原文档Tutorials / Créditos一节列出的 Martin Fowler《Gateway》文章、microservices.io 的 API Gateway 模式页等外部资料因其为仓库外链接此处不再输出 URL其内容要点统一接口、策略执行、请求转发已在上文结合仓库源码完整展开。赞分享示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载相关推荐Gateway 设计模式实战在 Java 项目中统一封装外部服务与 API 集成基于 java-design-patternsGateway 设计模式实战在 Java 项目中统一封装外部服务与 API 集成基于 java design patterns Gateway网关设计示例工程教程date-fns 阿非利卡语Afrikaanslocale 完整指南format 与 parse 行为快照解读date fns 阿非利卡语Afrikaanslocale 完整指南format 与 parse 行为快照解读 导读 本文以 date fns 仓库中 阿示例工程教程Java 设计模式实战指南以 java-design-patterns 开源仓库快速上手设计模式Java 设计模式实战指南以 java design patterns 开源仓库快速上手设计模式 本文以 java design patterns 仓库的 日示例工程教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →