本章主軸#
物件池(Object Pool)模式並未收錄在 GoF 經典書中,但在實務中極為常見。本章用作者親身經歷的金融網銀專案說明:當你內化了模式背後的原則,就算遇到不認識的問題,也能自己「推導出」適用的模式。
案例:金融網銀的中介層#
- 前端:Java servlet
- 中間層:作者用 C++ 編寫,透過 CORBA 與前端溝通
- 後端:透過 TCP/IP 與大型主機(mainframe)溝通
需求:
- 主要關注「吞吐量」而非單筆回應時間
- 多少條 TCP/IP 連線?沒人知道答案
- 1 條 → 太少
100 → 沒意義(頻寬瓶頸)
- 連線可能失敗,必須處理
高風險、又要快速完成。作者選擇先把高風險議題隔離成低風險。
設計起手式#
把 TCP/IP 連線抽象成 Port,並加入一個唯一的 PortManager:
Port:負責一條 TCP/IP 連線PortManager:負責建立與管理 Ports(用 Singleton 確保只有一個)
PortManager 的方法:
getInstanceOfPort():找一個 idle 的 Port 借出returnInstanceOfPort(Port p):把 Port 還回去returnBadPort(Port p):標記 Port 為壞,並補一個新的
Client 程式碼三步:「跟管理員借 Port → 用 → 還」。
Client 完全不需要知道有多少 Port、何時建立、何時失敗——這正是封裝的力量。
模式為何能輔助敏捷?#
XP 口號:YAGNI(You Ain’t Gonna Need It)。先做眼前最重要的事。
把 TCP/IP 的細節封到
PortManager後,作者可以先把 client 端的業務邏輯做完,等之後再回頭優化錯誤處理、負載平衡與連線數——而這些調整完全不會撼動 client 端。
錯誤處理也由 Pool 接管#
當 Port 出錯:
Port拋出例外- Client 捕捉到 → 還壞 Port → 跟 Manager 借新 Port → 重送
PortManager.returnBadPort()把壞 Port 換掉,必要時通知系統管理員
整套錯誤處理的內聚也都在 PortManager。
雙重檢查機制#
上線前作者擔心:上億美金過這條 pipeline,沒人在看。
受 Steve Maguire《Writing Solid Code》啟發:對任務關鍵程式做獨立的雙重檢查。
讓 PortManager 啟動一個額外執行緒,每 15 分鐘:
- 統計尚未完成的 Port 請求數
- 比對各 Port 狀態與請求數是否吻合
- 計算錯誤狀態下的 Port 數
由於整體已封裝得乾淨,這層健康檢查可隨時加上、加深,幾乎不影響其他程式碼。
Object Pool 的關鍵特性#
| 欄位 | 內容 |
|---|---|
| Intent | 管理那些「建立成本高」或「數量有限制」的物件之重用 |
| Problem | 物件的建立、上限、回收都得遵守規則 |
| Solution | Pool 提供 acquire 與 release;空了就 new、滿了就排隊 |
| Participants | ReusablePool、Reusable、Client |
| Consequences | 在「需求穩定」時運作良好;流量大幅起伏時要設置上限 |
| Implementation | 大多採 Singleton 限制 Pool;可附 release 方法在 Reusable 上自動回收 |
Object Pool 的論述見於 Mark Grand《Patterns in Java, Vol. 1》與 Clifton Nock《Data Access Patterns》(後者稱為 Resource Pool)。
工廠遠不只是製造#
從這個案例可以看到:工廠物件可以負責建立、管理、共享、重用、錯誤處理、健康檢查。一旦把責任挑明,結構自然浮現。
本章重點#
- 內化原則 → 在沒有現成模式時,也能推導出對的解
- 把高風險議題封裝成獨立物件,剩下的 client 就能享受 YAGNI
- Object Pool = Singleton + 物件池管理 + (常常)健康檢查
- 工廠物件可以做的遠多於 new 物件——它是「責任的家」