🎯 什麼情境該想到我

當你「程式需要產生極大量、細粒度、彼此又很相似的物件(文件裡的每個字元、地圖上的每棵樹、遊戲裡每一顆子彈),一個一個都建成完整物件會把記憶體吃光」的時候。

⚙️ 怎麼用(步驟 / 公式)

意圖:運用共享來有效率地支援大量細粒度的物件。關鍵是把物件狀態拆成可共享的「內在狀態」與不可共享的「外在狀態」。

主要參與者 / 結構:

  • Flyweight(享元):宣告可接受並作用於外在狀態的介面。
  • ConcreteFlyweight(具體享元):可共享的物件,只儲存內在狀態(與情境無關、可跨處重複使用,如字元的字形資料)。
  • FlyweightFactory(享元工廠):建立並管理享元;有人要時先查快取池,已存在就回傳共享的那一個,否則才新建。
  • Client:保存或計算外在狀態(與情境有關、如座標/顏色),在呼叫享元操作時把它傳入。

做法要點:

  1. 分析物件狀態,切出「內在(可共享)」與「外在(每次不同)」兩部分。
  2. 內在狀態放進享元物件;外在狀態移出,改由客戶端持有並在呼叫時傳入。
  3. 一律透過工廠取得享元,讓相同內在狀態的物件被重複共享。

🧪 我實際套用的紀錄

  • (待填)

⚠️ 注意 / 什麼時候不適用

  • 增加複雜度:要正確區分內在/外在狀態,並把外在狀態的管理責任丟給客戶端。
  • 用計算換記憶體:外在狀態每次傳入或重算可能增加執行時間。
  • 若物件數量本來就不多、或狀態幾乎都不能共享,省下的記憶體不值得這份複雜度。
  • 享元通常要是不可變的(immutable),共享的東西被改到會全部一起壞。

🔗 相關工具