🎯 什麼情境該想到我
當你「有一個物件狀態一改變,就要有一群其他物件跟著自動更新」的時候(例如事件/發布訂閱、MVC 裡 model 變了要通知多個 view、UI 資料綁定、股價即時看板)。
⚙️ 怎麼用(步驟 / 公式)
意圖:定義物件間一種一對多的依賴關係,當一個物件的狀態改變時,所有依賴於它的物件都會得到通知並自動更新。
主要參與者 / 結構:
- Subject(主題/被觀察者):維護一份觀察者清單,提供
attach()/detach(),狀態變化時notify()。 - Observer(觀察者介面):宣告
update(),供收到通知時被呼叫。 - ConcreteSubject:保存實際狀態,變化時通知所有觀察者。
- ConcreteObserver:實作
update(),收到通知後同步自己的狀態。
做法要點:
- 觀察者向主題註冊(訂閱)自己。
- 主題狀態改變時,逐一呼叫每個觀察者的
update()。 - 觀察者在
update()內拉取或接收新狀態,更新自己。 - 主題與觀察者只透過介面互動,主題不需知道觀察者的具體型別。
🧪 我實際套用的紀錄
- (待填)
⚠️ 注意 / 什麼時候不適用
- 通知順序通常不保證;一個更新又觸發別的更新,可能形成連鎖甚至循環,難追蹤也傷效能。
- 小心記憶體洩漏:觀察者用完沒
detach()(取消訂閱),主題會一直持有它。 - 觀察者一多,一次
notify()的成本與副作用都不易掌握。
🔗 相關工具
- 中介者模式 Mediator(中介者常以觀察者機制在同事間廣播變化)
- 命令模式 Command(都解耦觸發與反應,但命令是封裝單一請求、觀察者是廣播通知)
- 單例模式 Singleton(全域事件匯流排/主題常做成單例,但要留意其耦合缺點)
- 工具-針對介面編程(主題只依賴 Observer 介面,不綁具體觀察者)
- 工具-封裝變化點(把「有哪些對象關心這個變化」封裝成可動態增減的訂閱)
- 設計模式