文章目錄
- 🕊? 中介者模式(Mediator Pattern)深度解析
- 一、模式本質與核心價值
- 二、經典UML結構
- 三、Unity實戰代碼(成就系統協調)
- 1. 定義中介者接口與同事基類
- 2. 實現具體同事類
- 3. 實現具體中介者
- 4. 客戶端使用
- 四、模式進階技巧
- 1. 事件總線集成
- 2. 狀態依賴管理
- 3. 優先級路由
- 五、游戲開發典型應用場景
- 六、性能優化策略
- 七、模式對比與選擇
- 八、最佳實踐原則
- 九、常見問題解決方案
🕊? 中介者模式(Mediator Pattern)深度解析
——以Unity實現跨系統通信與復雜UI協調為核心案例
一、模式本質與核心價值
核心目標:
? 解耦對象間的直接依賴,通過中介者集中管理交互
? 簡化網狀通信為星型結構,提升系統可維護性
? 統一控制交互邏輯,便于擴展新通信規則
關鍵術語:
- Mediator(中介者接口):定義對象間通信的接口
- ConcreteMediator(具體中介者):實現協調邏輯
- Colleague(同事類):需要交互的對象,依賴中介者
數學表達:
設有N個對象,原始耦合度為O(N2),引入中介者M后降為O(N)
二、經典UML結構
三、Unity實戰代碼(成就系統協調)
1. 定義中介者接口與同事基類
public interface IMediator {void Notify(object sender, string eventType, object data = null);
}public abstract class Colleague : MonoBehaviour {[SerializeField] protected IMediator mediator;public void SetMediator(IMediator mediator) {this.mediator = mediator;}
}
2. 實現具體同事類
// 成就系統
public class AchievementSystem : Colleague {public void Unlock(string achievementID) {Debug.Log($"解鎖成就:{achievementID}");mediator?.Notify(this, "AchievementUnlocked", achievementID);}
}// UI彈窗系統
public class UIPopup : Colleague {public void ShowAchievementPopup(string title) {Debug.Log($"顯示成就彈窗:{title}");}
}// 音效系統
public class SFXSystem : Colleague {public void Play(string clipName) {Debug.Log($"播放音效:{clipName}");}
}
3. 實現具體中介者
public class AchievementMediator : IMediator {private AchievementSystem _achievement;private UIPopup _popup;private SFXSystem _sfx;public AchievementMediator(AchievementSystem a, UIPopup u, SFXSystem s) {_achievement = a;_popup = u;_sfx = s;_achievement.SetMediator(this);_popup.SetMediator(this);_sfx.SetMediator(this);}public void Notify(object sender, string eventType, object data) {switch(eventType) {case "AchievementUnlocked":HandleAchievementUnlocked(data.ToString());break;case "PopupClosed":HandlePopupClosed();break;}}private void HandleAchievementUnlocked(string id) {_popup.ShowAchievementPopup(GetAchievementTitle(id));_sfx.Play("AchievementUnlocked");SaveSystem.SaveAchievement(id);}private void HandlePopupClosed() {_sfx.Play("ButtonClick");}
}
4. 客戶端使用
public class GameManager : MonoBehaviour {[SerializeField] private AchievementSystem achievement;[SerializeField] private UIPopup popup;[SerializeField] private SFXSystem sfx;private IMediator _mediator;void Start() {_mediator = new AchievementMediator(achievement, popup, sfx);}void Update() {if(Input.GetKeyDown(KeyCode.A)) {achievement.Unlock("KILL_100_ENEMIES");}}
}
四、模式進階技巧
1. 事件總線集成
public class EventMediator : IMediator {private Dictionary<Type, List<Action<object>>> _handlers = new();public void Subscribe<T>(Action<T> handler) {var type = typeof(T);if(!_handlers.ContainsKey(type)) {_handlers[type] = new List<Action<object>>();}_handlers[type].Add(obj => handler((T)obj));}public void Notify(object sender, string eventType, object data) {if(_handlers.TryGetValue(data.GetType(), out var handlers)) {foreach(var h in handlers) h(data);}}
}
2. 狀態依賴管理
public class StateDependentMediator : IMediator {private Dictionary<GameState, Action<object>> _stateHandlers = new();public void RegisterStateHandler(GameState state, Action<object> handler) {_stateHandlers[state] = handler;}public void Notify(object sender, string eventType, object data) {if(_stateHandlers.TryGetValue(GameManager.CurrentState, out var handler)) {handler(data);}}
}
3. 優先級路由
public class PriorityMediator : IMediator {private List<(int priority, Action<object>)> _handlers = new();public void AddHandler(int priority, Action<object> handler) {_handlers.Add((priority, handler));_handlers.Sort((a,b) => b.priority.CompareTo(a.priority));}public void Notify(object sender, string eventType, object data) {foreach(var h in _handlers) {h.handler(data);}}
}
五、游戲開發典型應用場景
-
UI系統協調
public class UIMediator : IMediator {public void Notify(object sender, string eventType) {switch(eventType) {case "InventoryOpened":PauseGame();HideHUD();break;case "SettingsClosed":ResumeGame();ShowHUD();break;}} }
-
多人游戲同步
public class NetworkMediator : IMediator {public void Notify(object sender, string eventType, object data) {switch(eventType) {case "PlayerMove":BroadcastToAllClients(data);break;case "ChatMessage":ProcessChatMessage(data);break;}} }
-
任務系統協調
public class QuestMediator : IMediator {public void Notify(object sender, string eventType, Quest quest) {switch(eventType) {case "QuestStarted":UpdateQuestLog();PlayQuestStartSFX();break;case "QuestCompleted":GrantRewards();UpdateNPCdialogue();break;}} }
-
車輛控制系統
public class VehicleMediator : IMediator {public void Notify(object sender, string eventType) {if(sender is Engine && eventType == "Overheat") {ThrottleControl.ReducePower();CoolingSystem.ActivateEmergencyCooling();}} }
六、性能優化策略
策略 | 實現方式 | 適用場景 |
---|---|---|
事件過濾 | 提前終止不相關事件處理 | 高頻事件系統 |
批處理 | 合并多個通知為單個操作 | 物理系統更新 |
緩存路由表 | 預生成事件處理映射 | 固定事件類型 |
異步處理 | 使用UniTask處理耗時操作 | 網絡通信場景 |
七、模式對比與選擇
維度 | 中介者模式 | 觀察者模式 |
---|---|---|
關注點 | 集中協調 | 松散通知 |
耦合度 | 同事類依賴中介者 | 發布者/訂閱者解耦 |
復雜度 | 較高(需維護中介者) | 較低 |
典型場景 | 復雜交互協調 | 簡單事件通知 |
八、最佳實踐原則
- 職責分離:避免中介者成為"上帝對象"
- 接口最小化:
public interface IGameMediator {void PlayerAction(PlayerActionType action);void UIEvent(UIEventType event); }
- 模塊化中介者:
public class CompositeMediator : IMediator {private List<IMediator> _subMediators = new();public void AddMediator(IMediator m) => _subMediators.Add(m);public void Notify(object sender, string eventType, object data) {foreach(var m in _subMediators) m.Notify(sender, eventType, data);} }
- 異常隔離:
public void Notify(...) {try {// 處理邏輯} catch(Exception e) {Debug.LogError($"中介者處理異常:{e.Message}");} }
九、常見問題解決方案
Q1:如何防止中介者過度膨脹?
→ 實現分層中介者
public class HierarchyMediator : IMediator {private Dictionary<SystemType, IMediator> _subMediators = new();public void Notify(...) {if(_subMediators.TryGetValue(GetSystemType(sender), out var mediator)) {mediator.Notify(sender, eventType, data);}}
}
Q2:如何處理循環通知?
→ 實現事件標記
public class Notification {public string Type;public bool IsProcessed;
}public void Notify(...) {if(notification.IsProcessed) return;notification.IsProcessed = true;// 處理邏輯
}
Q3:如何調試復雜事件流?
→ 實現事件追蹤器
public class DebugMediator : IMediator {public void Notify(object sender, string eventType, object data) {Debug.Log($"[{Time.time}] 事件:{eventType} 發送者:{sender.GetType().Name}");// 傳遞給實際中介者...}
}
上一篇 【行為型之迭代器模式】游戲開發實戰——Unity高效集合遍歷與場景管理的架構精髓
下一篇 【行為型之備忘錄模式】游戲開發實戰——Unity存檔系統與狀態管理的終極解決方案