觀察者模式是一種行為設計模式,它定義了對象之間的一對多依賴關系,當一個對象的狀態發生改變時,所有依賴它的對象都會得到通知并自動更新。
優點:
??1.解耦性強??:
??觀察者(訂閱者)與主題(發布者)通過抽象接口通信,不直接依賴具體實現,??修改主題或觀察者的代碼時,無需影響對方,提升代碼可維護性。
2.??動態訂閱機制??:
??觀察者可隨時注冊或注銷,運行時靈活調整事件響應,支持熱插拔功能,增強系統擴展性。
3.??一對多通信高效??:
一個主題狀態變化可同時通知多個觀察者,避免重復調用邏輯,提升事件處理效率。
??4.支持事件驅動架構??:
通過事件總線(Event Bus)實現全局通信, ??簡化跨模塊通信,適合復雜系統交互。
缺點:
1.?性能開銷??:
高頻事件(如每幀更新)或大量觀察者時,遍歷通知列表耗時(物理引擎的CollisionEvent在百個對象碰撞時,觸發千次通知)。
??優化??:
1.使用事件合并(如積累多次位置更新后批量通知)。
2.異步處理(將事件推送到隊列,分幀處理)。
2.??內存泄漏風險??:
??觀察者未正確注銷時,Subject(主題者)持有其引用導致無法回收(Unity中,UI面板銷毀前未取消訂閱事件)。
??優化??:
使用弱引用(WeakReference)或者使用擴展方法在MonoBehaviour綁定取消事件注冊的方法,使其在OnDestroy時調用取消注冊方法。
public static void UnregisterOnDestroy(this MonoBehaviour obj, Action unsubscribe) {obj.gameObject.AddComponent<OnDestroyDispatcher>().OnDestroyEvent += unsubscribe;
}class OnDestroyDispatcher : MonoBehaviour {public event Action OnDestroyEvent;void OnDestroy() => OnDestroyEvent?.Invoke();
}
注:弱引用的使用 (會加一篇Unity中弱引用的測試使用的文章)。
3.??事件順序不可控??:
??觀察者處理事件的順序依賴注冊順序,可能導致邏輯錯誤。
??優化??:
引入優先級字段,按優先級排序觀察者。
4.?調試困難??:
??問題??:事件流分散,難以追蹤事件觸發源頭和傳遞鏈路。
??優化??:
添加事件日志:記錄每個事件的發布者和訂閱者。
說明例子:
1.UML圖:
2.實現:
1.實現Subject(主題者)基類:
public abstract class Subject{List<Observer> m_Observers = new List<Observer>();//加入觀察者public void Attach(Observer theObserver){m_Observers.Add(theObserver);}//刪除觀察者public void Detach(Observer theObserver){m_Observers.Remove(theObserver);}//通知所有觀察者public void Notify(){foreach (Observer theObserver in m_Observers){theObserver.Update();}}}
2.實現Observer(觀察者)基類:
public abstract class Observer{public abstract void Update();}
3.實現具體Subject:
public class ConcreteSubject : Subject{string m_SubjectState;public void SetState(string state){this.m_SubjectState = state;this.Notify();}public string GetState(){return this.m_SubjectState;}}
4.實現具體Observer:
//實現Observer1public class ConcreteObserver1 : Observer{ConcreteSubject m_Subject = null;public ConcreteObserver1(ConcreteSubject theSubject){this.m_Subject = theSubject;}public override void Update(){Debug.Log("ConcreteObserver1.Update");//獲取Subject狀態Debug.Log("ConcreteObserver1 : Subject 當前主題:" + m_Subject.GetState());}}//實現Observer2public class ConcreteObserver2 : Observer{ConcreteSubject m_Subject = null;public ConcreteObserver2(ConcreteSubject theSubject){this.m_Subject = theSubject;}public override void Update(){Debug.Log("ConcreteObserver2.Update");//獲取Subject狀態Debug.Log("ConcreteObserver2 : Subject 當前主題:" + m_Subject.GetState());}}
游戲中使用場景:
??1.成就/統計系統??:監聽關鍵游戲事件(擊殺、死亡、收集)--->玩家擊殺Boss后解鎖成就。
??2.UI更新??:將UI元素與游戲數據解耦--->血量變化時自動刷新血條UI。
??3.跨系統通信??:避免系統間直接引用--->背包系統物品使用后通知技能系統。
??4.AI行為觸發??:基于事件觸發的敵人反應---->玩家進入警戒范圍觸發敵人警報。
??5.網絡同步??:將本地事件廣播給其他客戶端--->玩家位置同步事件。
總結:
觀察者模式的核心價值??在于解耦和動態通信,但其性能、內存和調試問題需謹慎處理。
在游戲開發中,觀察者模式適用于以下場景:
1.需要松耦合的跨系統通信。
2.需要動態處理大量事件類型。
3.需要支持模塊化擴展(如MOD系統)。
參考書籍:
《Hands-On Game Development Patterns with Unity 2019》
《設計模式與游戲完美開發》