本章主軸#

物件池(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 出錯:

  1. Port 拋出例外
  2. Client 捕捉到 → 還壞 Port → 跟 Manager 借新 Port → 重送
  3. PortManager.returnBadPort() 把壞 Port 換掉,必要時通知系統管理員

整套錯誤處理的內聚也都在 PortManager

雙重檢查機制#

上線前作者擔心:上億美金過這條 pipeline,沒人在看

受 Steve Maguire《Writing Solid Code》啟發:對任務關鍵程式做獨立的雙重檢查

PortManager 啟動一個額外執行緒,每 15 分鐘:

  • 統計尚未完成的 Port 請求數
  • 比對各 Port 狀態與請求數是否吻合
  • 計算錯誤狀態下的 Port 數

由於整體已封裝得乾淨,這層健康檢查可隨時加上、加深,幾乎不影響其他程式碼。

Object Pool 的關鍵特性#

欄位內容
Intent管理那些「建立成本高」或「數量有限制」的物件之重用
Problem物件的建立、上限、回收都得遵守規則
SolutionPool 提供 acquirerelease;空了就 new、滿了就排隊
ParticipantsReusablePoolReusableClient
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 物件——它是「責任的家