設計模式之上下文對象設計模式

目錄

一、模式介紹

二、架構設計

三、Demo 示例

四、總結


一、模式介紹

上下文對象(Context Object)模式 最早由《Core J2EE Patterns》第二版提出,其核心目標是在多層或多組件間共享與當前作用域(如一次請求、一次會話、一次業務流程)相關的所有狀態和服務,消除各組件對底層環境細節(如協議、線程、本地存儲等)的直接依賴,從而提高系統的可復用性、可維護性和可測試性。Context Object 封裝了與某個 Scope 相關的數據與行為,使各層或模塊只需依賴該 Context,即可獲得所需服務或狀態,而無需顯式傳遞大量參數或直接引用環境 API。

使用場景與歷史背景

  • 在傳統多層應用中,每一層如果要訪問共享信息(如用戶憑證、事務、配置參數),通常需要將其作為參數顯式傳遞,導致方法簽名臃腫、可讀性差、易出錯。

  • 隨著 J2EE 應用復雜度提升,設計者發現將環境細節直接嵌入業務邏輯耦合度過高,維護成本激增。

  • 《Core J2EE Patterns》第二版總結了當時業界實踐,將這種“共享環境數據”抽象為 Context Object 模式,對應 ApplicationContext/ServletContext、Hibernate SessionContext 等典型用法。

解決問題

  • 解耦:業務組件不必直接依賴環境(HTTP、JNDI、線程等)接口,一律通過 Context 獲取所需信息或服務。

  • 集中管理:所有上下文相關的信息集中維護,便于調試、監控及擴展。

  • 生命周期一致性:Context 在作用域開始時創建,結束時統一銷毀,資源釋放更可控。

典型實現:

  • Apache Spark – SparkContext / SQLContext / StreamingContext

    聚合集群配置、調度、序列化、監控接口,并暴露 RDD/DataFrame/流計算等 API。

  • Flink – StreamExecutionEnvironment / ExecutionEnvironment

    封裝執行引擎配置、并行度、checkpoint、狀態后端等,用于構建批/流作業。


二、架構設計

以下為 Context Object 模式的標準 UML 類圖:

主要組件說明

  • Context(接口):定義獲取與存放上下文數據的方法。

  • ConcreteContext(實現類):內部維護一張屬性映射,負責實際存取。

  • ContextFactory(工廠類):(可選)根據環境創建對應的 Context 實例。

  • Client:業務組件,通過構造器或工廠獲取 Context 實例,并向其讀寫數據或調用存入的服務。


三、Demo 示例

問題場景:在一個 Web 應用或微服務中,常常需要在多個業務層(如控制層、服務層、數據訪問層)之間傳遞用戶會話信息、跟蹤操作日志對象以及可復用的工具服務實例。直接在每個方法簽名中傳遞這些參數,不僅會導致參數列表臃腫,還容易遺漏,增加維護成本。

解決方案:使用上下文對象模式,將所有需跨層共享的數據與服務封裝到一個 Context 對象中,由各層直接從 Context 中獲取,而不必在方法之間顯式傳遞這些參數。

// 1. 定義 Context 接口,提供讀寫屬性和服務獲取功能
public interface RequestContext {<T> T get(String key, Class<T> type);void set(String key, Object value);
}
?
// 2. Context 實現,內部維護屬性映射
public class RequestContextImpl implements RequestContext {private final Map<String, Object> data = new HashMap<>();
?@Overridepublic <T> T get(String key, Class<T> type) {return type.cast(data.get(key));}
?@Overridepublic void set(String key, Object value) {data.put(key, value);}
}
?
// 3. Context 工廠,初始化必要屬性
public class RequestContextFactory {public static RequestContext create(String userId) {RequestContext ctx = new RequestContextImpl();// 初始化用戶信息和日志追蹤器ctx.set("userId", userId);ctx.set("traceId", UUID.randomUUID().toString());return ctx;}
}
?
// 4. 控制層:創建 Context 并啟動業務流程
public class Controller {public void handleRequest(String userId) {RequestContext ctx = RequestContextFactory.create(userId);new BusinessService(ctx).process();}
}
?
// 5. 業務層:直接從 Context 獲取 userId 和 TraceId,執行業務邏輯
public class BusinessService {private final RequestContext ctx;
?public BusinessService(RequestContext ctx) {this.ctx = ctx;}
?public void process() {String userId = ctx.get("userId", String.class);String traceId = ctx.get("traceId", String.class);// 輸出日志時無需額外傳參System.out.println("[" + traceId + "] Processing business logic for user " + userId);
?// 調用下一層服務new DataService(ctx).execute();}
}
?
// 6. 數據訪問層:繼續復用同一個 Context
public class DataService {private final RequestContext ctx;
?public DataService(RequestContext ctx) {this.ctx = ctx;}
?public void execute() {String traceId = ctx.get("traceId", String.class);// 使用 traceId 進行 SQL 日志關聯System.out.println("[" + traceId + "] Executing SQL queries");}
}

說明

  • Controller 層只需創建并初始化一次 RequestContext,并傳遞給后續各層,不再維護多個參數。

  • 任何業務或數據訪問類均可通過 ctx.get(...) 獲取所需信息,簡化方法簽名。

  • 可擴展到添加更多上下文數據(如用戶權限列表、國際化配置、第三方服務客戶端等),只需在 Context 中新增屬性,而無需改動各層接口。


四、總結

上下文對象模式 通過封裝作用域相關的所有狀態與服務,實現組件與環境的最大解耦,提升系統的靈活性和可維護性。

  • 價值

    • 模塊化:各功能模塊僅依賴 Context 接口,無須關注如何獲取底層資源。

    • 擴展性:新增上下文數據或服務時,只需修改 Context 實現,無需改動業務層代碼。

    • 測試友好:可為單元測試提供 Mock Context,對業務邏輯進行隔離測試。

  • 注意事項

    • 避免 Context 過于龐大,必要時可拆分為多個子 Context(如 ConfigContext、SecurityContext)。

    • 隨著系統復雜度上升,建議引入成熟的 IoC/DI 容器(如 Spring ApplicationContext)來管理對象生命周期和依賴注入。

Context Object 模式是企業級應用架構中常見且行之有效的方案,既可手寫實現,也可借助框架。它在《Core J2EE Patterns》一書中的提煉,為現代微服務與云原生開發中的“作用域數據共享”提供了理論基礎與實踐指導。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/87555.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/87555.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/87555.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

@Linux服務器加域退域

文章目錄 **一、加入Active Directory域****1. 準備工作****2. 配置步驟****步驟1&#xff1a;驗證網絡和DNS****步驟2&#xff1a;發現域****步驟3&#xff1a;加入域****步驟4&#xff1a;配置SSSD&#xff08;可選&#xff09;****步驟5&#xff1a;配置sudo權限&#xff08…

鴻蒙系統(HarmonyOS)4.2 設備上實現無線安裝 APK 并調試

在鴻蒙系統&#xff08;HarmonyOS&#xff09;4.2 設備上實現無線安裝 APK 并調試的步驟與 Android 類似&#xff0c;但需注意鴻蒙系統的特殊設置。以下是詳細操作指南&#xff1a; 鴻蒙系統特殊準備 開啟開發者選項&#xff1a; - 設置 > 關于手機 > 連續點擊"H…

MyBatis時間戳查詢實戰指南

在 MyBatis 中通過時間戳&#xff08;Timestamp&#xff09;作為查詢條件&#xff0c;需注意數據庫時間類型與 Java 類型的映射。以下是具體實現方式&#xff1a; 一、Java 實體類與數據庫字段映射 實體類定義 使用 java.sql.Timestamp 或 java.time.LocalDateTime&#xff08;…

【Verilog硬件語言學習筆記4】FPGA串口通信

串口通信是系統設計中比較基部分&#xff0c;其原理其實也很通俗易懂。單次建立通信會傳輸8個bit&#xff0c;其時序也很簡單&#xff0c;這里就不再贅述了。其對應的實例代碼如下所示&#xff1b; 首先是接受部分&#xff08;因為我的變量命名也很規范&#xff0c;通俗易懂&a…

Go 語言安裝教程(Windows 系統)

2025年07月02日 準備工作 確認系統為 Windows 7 及以上版本&#xff08;推薦 Windows 10/11&#xff09;。64 位系統選擇 amd64 版本安裝包&#xff0c;32 位系統選擇 386 版本。確保安裝目錄&#xff08;默認 C:\Program Files\Go\&#xff09;有至少 1GB 空間。 下載安裝包…

接口測試之postman

一、Postman功能簡介 3天精通Postman接口測試&#xff0c;全套項目實戰教程&#xff01;&#xff01; Postman是由Postdot Technologies公司打造的一款功能強大的調試HTTP接口的工具。在做接口測試的時候&#xff0c;Postman相當于一個客戶端&#xff0c;它可以模擬用戶發起的各…

【記錄】Ubuntu安裝Mysql

本文記錄Ubuntu系統下安裝Mysql 1 查看系統信息 lsb_release -a 2 使用apt下載安裝Mysql 1 打開終端,首先更新你的系統包索引,以確保所有包都是最新的 sudo apt update 2 安裝mysql服務器 sudo apt install mysql-server (也可以選擇對應的mysql-server 版本) 3 查看mysql狀…

【深度學習:進階篇】--4.1.循環神經網絡(改進)

RNN存在的問題&#xff1a;梯度爆炸&#xff0c;長期依賴參數量過大等問題 目錄 1.GRU(門控循環單元) 1.1.什么是GRU 1.2.直觀理解 1.3.本質解決問題 2.LSTM(長短記憶網絡) 2.1.作用 3.結構擴展與效率優化? 1.GRU(門控循環單元) 2014年&#xff0c;出現的算法&#x…

中心化錢包安全方案

先來看獨立的密鑰安全技術 1 自建或單租戶 CloudHSM 優點&#xff1a;密鑰永不出硬件&#xff0c;無法導出&#xff0c;只能對外提供公鑰。 交易時&#xff0c;外部應用把消息哈希傳進去簽名&#xff0c;再把簽好名的結果拿出來用。 這種方式安全性拉滿&#xff0c;但成本高、…

Android 實現底部彈窗

文章目錄在 Android 中創建優雅的底部選項彈窗 (BottomSheetDialogFragment) &#x1f4f1;第一步&#xff1a;設計底部彈窗的布局 &#x1f3a8;第二步&#xff1a;創建 BottomSheetDialogFragment 類 ??第三步&#xff1a;觸發并顯示底部彈窗 &#x1f680;在 Android 中創…

LAN8720 寄存器概覽和STM32 HAL庫讀寫測試

目錄 寄存器0x00:Basic Control Register&#xff08;BCR&#xff09;0x01:Basic Status Register&#xff08;BSR&#xff09; 連接測試寄存器讀寫測試 補充 寄存器 // 0x00:Basic Control Register&#xff08;BCR&#xff09; BIT15:Soft Reset 寫1復位&#xff0c;寫1之…

滲透測試深度分析:空密碼Administrator賬戶引發的安全風暴

滲透測試深度分析&#xff1a;空密碼Administrator賬戶引發的安全風暴0x01 測試背景 在內網滲透測試中&#xff0c;對Windows主機 192.168.1.98 使用 enum4linux 進行枚舉&#xff1a; enum4linux -u Administrator -p -a 192.168.1.98關鍵發現&#xff1a;Administrator賬戶空…

OpenCV CUDA模塊設備層-----高效地計算兩個 uint 類型值的帶權重平均值

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 OpenCV 的 CUDA 模塊&#xff08;cudev&#xff09; 中的一個設備端內聯函數&#xff0c;用于高效地計算兩個 uint 類型值的帶權重平均值。 該函…

[學習記錄]Unity毛發渲染[URP]-Shell基礎版

毛發&#xff0c;無論是人類的頭發、動物的皮毛&#xff0c;還是奇幻生物的絨毛&#xff0c;都是構成生命感和真實感不可或缺的元素。它對光線的獨特散射、吸收和反射&#xff0c;賦予了物體柔軟、蓬松、有生命力的質感。它不僅僅是讓角色看起來更“毛茸茸”那么簡單&#xff0…

數字孿生技術引領UI前端設計潮流:增強現實(AR)的集成應用

hello寶子們...我們是艾斯視覺擅長ui設計、前端開發、數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩!一、引言&#xff1a;AR 與數字孿生融合的設計革新浪潮在體驗經濟與技術融合的雙重驅動下&…

碰一碰發視頻源碼搭建與定制化開發:支持OEM

在近場通信&#xff08;NFC&#xff09;技術與移動終端深度融合的背景下&#xff0c;“碰一碰發視頻” 功能憑借便捷的交互體驗&#xff0c;在商業推廣、信息傳遞等場景中快速落地。不同于標準化解決方案的黑盒模式&#xff0c;基于源碼的定制化開發能從底層優化傳輸效率、提升…

Ubuntu 24.04 安裝配置 Redis 7.0 開機自啟

下載源碼 wget https://download.redis.io/releases/redis-7.0.12.tar.gz安裝依賴 & 準備環境 sudo apt update && sudo apt upgrade -y sudo apt install -y build-essential tcl curl解壓 tar xzf redis-7.0.12.tar.gz編譯安裝 cd redis-7.0.12 make -j$(nproc) …

【Linux 系統】基礎IO——Linux中對文件的理解

13.基礎IO(1) 文章目錄13.基礎IO(1)文件的基本概念&#xff1a;內容與屬性文件的打開機制&#xff1a;fopen 和 open被打開的文件與磁盤文件的區別文件的內核數據結構文件與進程的交互方式標準輸入/輸出/錯誤與文件流系統調用與文件描述符文件打開模式&#xff08;r/w/a/a&…

Go調度器的搶占機制:從協作式到異步搶占的演進之路|Go語言進階(7)

想象一下這樣的場景&#xff1a;你在餐廳排隊等位&#xff0c;前面有個人點了餐卻一直霸占著座位玩手機&#xff0c;后面的人只能干等著。這就是Go早期版本面臨的問題——一個goroutine如果不主動讓出CPU&#xff0c;其他goroutine就只能餓著。 今天我們來聊聊Go調度器是如何解…

開源模型應用落地-讓AI更懂你的每一次交互-Mem0集成Qdrant、Neo4j與Streamlit的創新實踐(四)

一、前言 在人工智能迅速發展的今天,如何讓AI系統更懂“你”?答案或許藏在個性化的記憶管理之中。Mem0作為一個開源的記憶管理系統,正致力于為AI賦予長期記憶與個性化服務能力。通過結合高性能向量數據庫Qdrant、圖數據庫Neo4j的強大關系分析能力以及Streamlit的高效可視化交…