news 2026/9/30 10:55:31

java-design-patterns 项目实战:Context Object(上下文对象)模式在分层应用中的协议无关数据共享

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
java-design-patterns 项目实战:Context Object(上下文对象)模式在分层应用中的协议无关数据共享
  • 示例工程
  • 教程

【免费下载链接】java-design-patterns

Design patterns implemented in Java

项目地址:https://gitcode.com/GitHub_Trending/ja/java-design-patterns
点击查看免费下载

导读

Context Object(上下文对象)模式是 Core J2EE 经典设计模式之一,其核心思想是把与具体协议/环境绑定的上下文数据(如请求、会话、安全凭证)抽取出来,封装进一个与协议无关的普通对象中,再跨层共享传递。本文以 java-design-patterns 仓库中context-object模块(含阿拉伯语文档 localization/ar/context-object/README.md 与英文版 context-object/README.md)为主线,结合完整源码与测试,讲解该模式的意图、三层传递实现、工厂创建方式、适用场景与权衡,并给出可运行验证方式。读完你将掌握如何用 Context Object 避免在多层系统中逐参数传递、如何保持层间解耦,以及它在 SpringApplicationContext、JAX-RSSecurityContext等真实框架中的对应形态。

模式概览:名称、别名与意图

  • 名称 / 分类:Context Object(上下文对象),属于创建型(Creational)到行为型(Behavioral)之间用于组织上下文数据的设计模式;在英文版 README 中归类为 Behavioral,并打有Context、Decoupling、Encapsulation、Session management等标签。
  • 别名:Context、Context Encapsulation、Context Holder、Encapsulate Context(上下文封装 / 上下文持有者 / 封装上下文),阿拉伯语文档中对应“السياق、تجميع السياق”(上下文、上下文聚合)。
  • 意图:将状态与行为封装进与具体协议无关的上下文对象中,使应用组件与环境的复杂性解耦,并以统一方式在整个应用中共享上下文状态。

来自 Core J2EE Patterns 的经典表述(阿拉伯语文档第 31-33 行亦引用):

使用 Context Object,以与协议无关的方式封装状态,并在整个应用中共享。

通俗解释(文档“In plain words”):

创建一个对象来存储上下文数据,然后把这个对象传递到任何需要它的地方。

模式动机:为什么需要上下文对象

阿拉伯语文档给出的现实世界例子是一个多分层应用:系统包含 A、B、C 等多个带标签的层,每层都要从同一个上下文中提取特定信息供后续使用。如果逐条把信息作为参数单独传递,将非常低效;此时需要一个既能存储又能高效传递信息的手段。

英文版 README 用机场登机流程做类比:乘客从值机、安检、登机到客服,多个服务都需要共享乘客身份、航班、偏好等数据。与其让每个服务单独索取并逐项传递,不如维护一个统一的“乘客上下文对象”,各服务按需读取或更新。这与软件中的 Context Object 模式完全同构——既保证了信息一致性,又避免了服务间的紧耦合。

项目中的实现剖析:源码级拆解

本模块源码位于 context-object/src/main/java/com/iluwatar/context/object/,共 6 个类,职责清晰:

类角色文件路径
ServiceContext协议无关的上下文载体(POJO)ServiceContext.java
ServiceContextFactory创建上下文的静态工厂ServiceContextFactory.java
LayerA第一层:创建上下文并写入 account 信息LayerA.java
LayerB第二层:从 LayerA 取上下文,追加 session 信息LayerB.java
LayerC第三层:从 LayerB 取上下文,追加 search 信息LayerC.java
App演示入口,串联三层调用App.java

1. 定义上下文载体:ServiceContext

ServiceContext只持有三个业务相关字段,不带任何协议/框架依赖:

@Getter @Setter public class ServiceContext { String accountService; String sessionService; String searchService; }

注意:源码中的字段命名是驼峰式的accountService、sessionService、searchService,并通过 Lombok 的@Getter/@Setter自动生成 getter/setter(getAccountService()、setSessionService()等);而阿拉伯语文档与 UML 图中使用了大写风格的ACCOUNT_SERVICE等命名。两处命名风格不同,但结构等价——字段名只是标识符,模式语义完全一致。

2. 统一创建入口:ServiceContextFactory

为保证应用各部分以一致方式获得上下文实例,仓库提供了静态工厂:

public class ServiceContextFactory { public static ServiceContext createContext() { return new ServiceContext(); } }

工厂的 Javadoc 明确其职责是“创建可在各层间传递的上下文对象的接口”(见 ServiceContextFactory.java)。把new ServiceContext()收敛到工厂方法,便于日后扩展——例如按环境注入不同实现、加入默认值或池化,调用方无需改动。

3. 三层传递:LayerA → LayerB → LayerC

三个层类通过构造函数接收上一层并取出其持有的同一上下文对象,实现“引用传递、增量填充”:

@Getter public class LayerA { private ServiceContext context; public LayerA() { context = ServiceContextFactory.createContext(); } public void addAccountInfo(String accountService) { context.setAccountService(accountService); } } @Getter public class LayerB { private ServiceContext context; public LayerB(LayerA layerA) { this.context = layerA.getContext(); } public void addSessionInfo(String sessionService) { context.setSessionService(sessionService); } } @Getter public class LayerC { public ServiceContext context; public LayerC(LayerB layerB) { this.context = layerB.getContext(); } public void addSearchInfo(String searchService) { context.setSearchService(searchService); } }

关键点:

  • 创建发生在第一层:LayerA构造时通过ServiceContextFactory.createContext()首次实例化上下文。
  • 后续层只做传递与增量写入:LayerB、LayerC分别从上一层的getContext()拿到同一个上下文实例,再分别补充 session、search 信息,而无需感知上下文内部结构。
  • UML 佐证:context-object/etc/context-object.urm.puml 中可以看到LayerB ..|> LayerA、LayerC ..|> LayerB的依赖关系,以及ServiceContext --> LayerA/B/C的引用关系和ServiceContextFactory ..|> ServiceContext的创建关系,与代码完全对应。

4. 运行演示:App 入口

App.java 串联整个流程:

@Slf4j public class App { private static final String SERVICE = "SERVICE"; public static void main(String[] args) { // 第一层:创建上下文并写入 account 信息 var layerA = new LayerA(); layerA.addAccountInfo(SERVICE); logContext(layerA.getContext()); // 第二层:沿用第一层的上下文,追加 session 信息 var layerB = new LayerB(layerA); layerB.addSessionInfo(SERVICE); logContext(layerB.getContext()); // 第三层:沿用前两层的上下文,追加 search 信息 var layerC = new LayerC(layerB); layerC.addSearchInfo(SERVICE); logContext(layerC.getContext()); } private static void logContext(ServiceContext context) { LOGGER.info("Context = {}", context); } }

阿拉伯语文档给出的输出示意(字段依次为 account / session / search):

Context = SERVICE null null Context = SERVICE SERVICE null Context = SERVICE SERVICE SERVICE

可以看到上下文对象在各层“接力”中被不断充实——这正是“存储 + 共享”模式的直观体现。英文版 README 记录的真实运行日志打印的是对象引用(如ServiceContext@5577140b),三次输出指向同一对象实例,同样印证了“同一上下文跨层共享”的语义。

测试验证:模式语义的自动化保障

本模块测试位于 context-object/src/test/java/com/iluwatar/contect/object/(注意测试包名contect为仓库既有拼写),核心断言来自 ServiceContextTest.java:

  • testSameContextPassedBetweenLayers:使用assertSame断言 LayerA、LayerB、LayerC 拿到的上下文是同一个对象实例,直接验证“引用共享”而非拷贝复制;
  • testScopedDataPassedBetweenLayers:LayerA 写入 account、LayerC 写入 search 后,account 与 search 均等于SERVICE,而 session 仍为null,验证各层写入的字段作用域互不污染、上下文增量填充正确;
  • testLayerContexts:按层逐步断言——LayerA 只有 account 有值、LayerB 增加 session 有值、LayerC 三个字段全部有值,完整覆盖三层递增填充的时序。

此外 AppTest.java 用assertDoesNotThrow保证App.main可无异常执行。context-object/pom.xml中声明了 JUnit Jupiter 与 SLF4J/Logback 依赖(context-object/pom.xml),说明该项目使用 JUnit 5 进行单元测试、SLF4J 输出日志。

何时使用 Context Object 模式

结合阿拉伯语文档(“适用性”章节)与英文版 README 的“When to Use”,适用场景包括:

  • 跨层共享信息:在系统不同层/组件之间共享上下文数据,避免把环境相关信息散落进业务逻辑;
  • 协议无关的数据分离:把数据从特定协议(HTTP、Servlet、JAX-RS 等)绑定类中解耦出来,存入独立于底层协议的对象;
  • 按需暴露接口:只向调用方暴露与当前上下文相关的 API,隐藏不必要的环境细节;
  • Web 应用请求封装:封装请求相关的信息(请求/响应对象、会话、用户偏好、安全凭证),使其在整个应用中易于访问,无需在函数间显式逐参数传递;
  • 分布式系统:封装任务上下文、用户偏好或安全凭证,便于跨组件、跨服务传播。

真实世界对应形态

文档列出的知名框架示例(均为上下文对象的工业级实例):

  • Spring:ApplicationContext——作为整个 Spring 容器的中央上下文对象,封装 Bean 定义、环境信息并对外共享;
  • Oracle Java EE:javax.ws.rs.core.SecurityContext——封装与安全相关的上下文信息;
  • Oracle Java EE:javax.servlet.ServletContext——封装 Servlet 容器级的共享上下文。

(以上链接原文分别指向 Spring 官方 Javadoc 与 Oracle Java EE API 文档。)

优点与权衡

优点(Benefits):

  • 解耦(Decoupling):组件与服务不再依赖执行环境的特定细节,模块化与可维护性提升;
  • 集中化(Centralization):上下文信息集中在一处,更易管理、访问与调试;
  • 灵活(Flexibility):上下文管理可随环境或需求变化而动态调整。

权衡(Trade-offs):

  • 开销(Overhead):若实现不当,上下文对象会引入额外的性能开销;
  • 膨胀风险(Complexity):若上下文对象设计不佳,容易变成臃肿复杂、难以维护的“上帝对象”。因此实践中建议字段按领域收敛、避免把所有信息都塞进同一个上下文。

与相关模式的关系

  • Singleton(单例):Context Object 常以 Singleton 方式实现,以保证全局唯一的访问点(本项目三层共享同一实例,语义上接近单实例共享);
  • Strategy(策略):Context Object 可组合策略,根据所封装上下文调整自身行为;
  • Decorator(装饰器):可为 Context Object 动态增加职责。

如何运行与验证本模块

仓库根 pom.xml 已将context-object声明为子模块(第 106 行)。在仓库根目录下执行 Maven 即可构建并运行测试:

./mvnw -pl context-object test
  • -pl context-object:仅构建该模块;
  • test:运行 JUnit 5 测试,覆盖“同一实例跨层传递”与“三层字段递增填充”等断言;
  • 如需观察演示输出,可运行App的主方法(com.iluwatar.context.object.App),其日志依赖已在 context-object/pom.xml 中配置 SLF4J + Logback。

小结

Context Object 模式用“一个协议无关的载体对象 + 一次创建、跨层引用传递”的方式,优雅地解决了多层系统中上下文数据共享与协议解耦两大问题。java-design-patterns 仓库的context-object模块通过ServiceContext、ServiceContextFactory与 LayerA/B/C 三层,给出了最小可运行且附带完整测试的参考实现;从 SpringApplicationContext到 Servlet/Security Context,都能看到该模式在企业级框架中的实战影子。若你的应用正面临“层层传参、环境逻辑侵入业务”的困境,不妨按此模式提炼一个自己的上下文对象。

  • 示例工程
  • 教程

【免费下载链接】java-design-patterns

Design patterns implemented in Java

项目地址:https://gitcode.com/GitHub_Trending/ja/java-design-patterns
点击查看免费下载

相关推荐

上一篇:智能流程版本管理:JeecgBoot如何实现AI驱动的流程版本控制
下一篇:无需复杂配置,5分钟搭建企业级实时客服系统:Coolify实时通信能力详解

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 10:53:34

GEO优化技术怎么选?从AI搜索抓取机制看评估与选型

凌晨两点,监控告警:入口 CPU 打到 92%,Nginx 日志里全是 DeepSeek-Bot、Bytespider、YuanbaoBot 的请求,QPS 从 200 窜到 1800,回源全打在 /article/detail 和 /sitemap.xml。第一反应是 CC 攻击,看下 UA 和…

作者头像 李华
网站建设 2026/9/30 10:53:12

DPDK性能调优实战:绕开BIOS、NUMA、Cache伪共享等90%翻车点

简介:本资源是《深入浅出DPDK》一书的系统性读书笔记PDF,面向网络高性能编程初学者、DPDK开发工程师及NFV/SDN领域技术人员,聚焦解决传统内核态网络栈在万兆以上场景下的中断开销大、吞吐瓶颈等核心问题。笔记完整覆盖DPDK基础原理&#xff0…

作者头像 李华
网站建设 2026/9/30 10:49:04

8511张YOLO格式DMS疲劳驾驶数据集:从拆包到YOLOv8训练全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/30 10:47:14

Nginx性能优化全链路诊断与治理手册

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/30 10:45:15

新媒体多平台批量发布流程详解

一、流程概述当下新媒体运营已全面进入矩阵化时代,个人自媒体、小型运营团队及中小品牌企业,均会布局公众号、视频号、抖音、小红书、知乎等多渠道平台。多平台同步运营,能够打破单一流量局限,拓宽内容传播边界,精准触…

作者头像 李华