C#和Unity中的中介者模式使用方式
作者:_克克克
中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性
C#中的中介者模式详解
中介者模式(Mediator Pattern)是一种行为设计模式,它能减少对象之间混乱无序的依赖关系,通过引入一个中介者对象来封装一系列对象之间的交互。
一、中介者模式的基本概念
1. 定义
中介者模式定义了一个对象来封装一组对象之间的交互方式,使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
2. 组成要素
- Mediator(中介者接口) :定义各个同事对象通信的接口
- ConcreteMediator(具体中介者) :实现中介者接口,协调各同事对象的交互
- Colleague(同事类) :每个同事对象都知道它的中介者对象,与其他同事通信时都通过中介者
3. 模式结构
[同事A] ────> [中介者] <─── [同事B]
↑____________|____________↑
二、中介者模式的特点
1. 优点
- 降低耦合度:将对象之间的网状结构变为星型结构
- 集中控制:将交互复杂性集中到中介者中
- 简化对象协议:用一对多的交互代替多对多的交互
- 易于扩展:新增同事类只需修改中介者或新增具体中介者
2. 缺点
- 中介者可能变得复杂:如果同事类过多,中介者会变得庞大复杂
- 过度集中化:中介者集中了太多控制逻辑,可能成为"上帝对象"
三、中介者模式的实现方式
1. 基本实现
// 中介者接口
public interface IMediator
{
void Notify(object sender, string ev);
}
// 基础同事类
public abstract class Colleague
{
protected IMediator _mediator;
public Colleague(IMediator mediator)
{
_mediator = mediator;
}
}
// 具体同事A
public class ConcreteColleagueA : Colleague
{
public ConcreteColleagueA(IMediator mediator) : base(mediator) { }
public void DoA()
{
Console.WriteLine("ColleagueA does A.");
_mediator.Notify(this, "A");
}
public void DoB()
{
Console.WriteLine("ColleagueA does B.");
}
}
// 具体同事B
public class ConcreteColleagueB : Colleague
{
public ConcreteColleagueB(IMediator mediator) : base(mediator) { }
public void DoC()
{
Console.WriteLine("ColleagueB does C.");
_mediator.Notify(this, "C");
}
public void DoD()
{
Console.WriteLine("ColleagueB does D.");
}
}
// 具体中介者
public class ConcreteMediator : IMediator
{
private ConcreteColleagueA _colleagueA;
private ConcreteColleagueB _colleagueB;
public ConcreteColleagueA ColleagueA
{
set { _colleagueA = value; }
}
public ConcreteColleagueB ColleagueB
{
set { _colleagueB = value; }
}
public void Notify(object sender, string ev)
{
if (ev == "A")
{
Console.WriteLine("Mediator reacts on A and triggers:");
_colleagueB.DoC();
}
if (ev == "C")
{
Console.WriteLine("Mediator reacts on C and triggers:");
_colleagueA.DoB();
_colleagueB.DoD();
}
}
}
2. 使用示例
// 客户端代码
var mediator = new ConcreteMediator();
var colleagueA = new ConcreteColleagueA(mediator);
var colleagueB = new ConcreteColleagueB(mediator);
mediator.ColleagueA = colleagueA;
mediator.ColleagueB = colleagueB;
Console.WriteLine("Client triggers operation A.");
colleagueA.DoA();
Console.WriteLine();
Console.WriteLine("Client triggers operation C.");
colleagueB.DoC();
3. 更复杂的实现(聊天室示例)
// 中介者接口
public interface IChatRoom
{
void Register(Participant participant);
void Send(string from, string to, string message);
}
// 具体中介者 - 聊天室
public class ChatRoom : IChatRoom
{
private Dictionary<string, Participant> _participants = new Dictionary<string, Participant>();
public void Register(Participant participant)
{
if (!_participants.ContainsKey(participant.Name))
{
_participants.Add(participant.Name, participant);
}
participant.ChatRoom = this;
}
public void Send(string from, string to, string message)
{
if (_participants.TryGetValue(to, out var participant))
{
participant.Receive(from, message);
}
}
}
// 同事基类
public abstract class Participant
{
public string Name { get; }
public IChatRoom ChatRoom { get; set; }
protected Participant(string name)
{
Name = name;
}
public void Send(string to, string message)
{
ChatRoom.Send(Name, to, message);
}
public abstract void Receive(string from, string message);
}
// 具体同事类
public class User : Participant
{
public User(string name) : base(name) { }
public override void Receive(string from, string message)
{
Console.WriteLine($"{from} to {Name}: '{message}'");
}
}
// 使用
var chatRoom = new ChatRoom();
var john = new User("John");
var jane = new User("Jane");
chatRoom.Register(john);
chatRoom.Register(jane);
john.Send("Jane", "Hi Jane!");
jane.Send("John", "Hello John!");
四、中介者模式的使用场景
1. 典型使用场景
- 对象间存在复杂的引用关系:当系统中对象之间存在复杂的网状引用关系,导致系统结构混乱且难以理解时。
- 需要集中控制对象间的交互:当多个类之间有复杂的交互逻辑,且这些逻辑需要集中管理时。
- 想定制分布在多个类中的行为:当行为分布在多个类中,但又需要根据需求改变这些行为时。
- GUI组件交互:图形用户界面中,各种控件(按钮、文本框等)之间的交互。
- 消息传递系统:如聊天应用、通知系统等需要多方通信的场景。
2. 实际应用示例
示例1:航空管制系统
// 航空交通管制中介者接口
public interface IAirTrafficControl
{
// 注册飞机到管制系统
void RegisterAircraft(Aircraft aircraft);
// 发送警告消息(发送者飞机 + 消息内容)
void SendWarningMessage(Aircraft sender, string message);
}
// 飞机类(同事类)
public class Aircraft
{
// 飞机呼号(唯一标识)
public string CallSign { get; }
// 持有对航空管制中心(中介者)的引用
private IAirTrafficControl _atc;
// 构造函数:初始化飞机并注册到管制系统
public Aircraft(string callSign, IAirTrafficControl atc)
{
CallSign = callSign;
_atc = atc;
_atc.RegisterAircraft(this); // 自动注册到管制系统
}
// 发送警告消息(通过管制中心转发)
public void SendWarning(string message)
{
// 不直接联系其他飞机,而是通过管制中心发送
_atc.SendWarningMessage(this, message);
}
// 接收来自其他飞机的警告
public void ReceiveWarning(string from, string message)
{
// 打印接收到的警告信息
Console.WriteLine($"{CallSign} received from {from}: {message}");
}
}
// 塔台管制中心(具体中介者实现)
public class Tower : IAirTrafficControl
{
// 保存所有注册的飞机列表
private List<Aircraft> _aircrafts = new List<Aircraft>();
// 注册飞机到管制系统
public void RegisterAircraft(Aircraft aircraft)
{
// 防止重复注册
if (!_aircrafts.Contains(aircraft))
{
_aircrafts.Add(aircraft);
}
}
// 处理警告消息转发
public void SendWarningMessage(Aircraft sender, string message)
{
// 遍历所有已注册的飞机(排除发送者自己)
foreach (var aircraft in _aircrafts.Where(a => a != sender))
{
// 将消息转发给其他飞机
aircraft.ReceiveWarning(sender.CallSign, message);
}
}
}
示例2:订单处理系统
// 订单中介者接口
public interface IOrderMediator
{
// 通知方法:组件通过此方法与中介者通信
// sender - 触发事件的组件
// eventType - 事件类型标识
void Notify(OrderComponent sender, string eventType);
}
// 订单组件基类(抽象同事类)
public abstract class OrderComponent
{
// 持有对中介者的引用
protected IOrderMediator _mediator;
// 构造函数:注入中介者实例
public OrderComponent(IOrderMediator mediator)
{
_mediator = mediator;
}
}
// 库存系统(具体同事类)
public class InventorySystem : OrderComponent
{
// 构造函数:调用基类构造函数
public InventorySystem(IOrderMediator mediator) : base(mediator) { }
// 检查库存方法
public void CheckStock()
{
Console.WriteLine("Checking stock...");
// 通知中介者库存已检查
_mediator.Notify(this, "StockChecked");
}
// 更新库存方法
public void UpdateStock()
{
Console.WriteLine("Updating stock...");
}
}
// 支付系统(具体同事类)
public class PaymentSystem : OrderComponent
{
// 构造函数:调用基类构造函数
public PaymentSystem(IOrderMediator mediator) : base(mediator) { }
// 处理支付方法
public void ProcessPayment()
{
Console.WriteLine("Processing payment...");
// 通知中介者支付已处理
_mediator.Notify(this, "PaymentProcessed");
}
}
// 订单中介者实现(具体中介者)
public class OrderMediator : IOrderMediator
{
// 持有库存系统引用
private InventorySystem _inventory;
// 持有支付系统引用
private PaymentSystem _payment;
// 构造函数:注入需要的组件
public OrderMediator(InventorySystem inventory, PaymentSystem payment)
{
_inventory = inventory;
_payment = payment;
}
// 实现通知处理方法
public void Notify(OrderComponent sender, string eventType)
{
// 如果是库存系统且事件类型为"StockChecked"
if (sender is InventorySystem && eventType == "StockChecked")
{
// 触发支付系统处理支付
_payment.ProcessPayment();
}
// 如果是支付系统且事件类型为"PaymentProcessed"
else if (sender is PaymentSystem && eventType == "PaymentProcessed")
{
// 更新库存
_inventory.UpdateStock();
Console.WriteLine("Order completed!");
}
}
}
五、中介者模式与其他模式的关系
与外观模式的区别:
- 外观模式为子系统提供简化接口,但不添加新功能
- 中介者模式集中同事对象间的通信,可以添加协调逻辑
与观察者模式的区别:
- 观察者模式通过订阅/发布机制实现单向通信
- 中介者模式对象间通过中介者进行双向通信
与命令模式结合:
- 可以使用命令模式将请求封装为对象,由中介者管理这些命令
六、最佳实践
合理划分责任:
- 中介者应只负责协调,不承担业务逻辑
- 避免创建"上帝对象"
考虑使用事件:
- 在C#中可以使用事件机制实现轻量级中介者
适度使用:
- 只在对象间交互确实复杂时使用
- 简单交互直接引用可能更合适
可测试性设计:
- 使中介者易于替换,方便单元测试
性能考虑:
- 高频交互场景需评估中介者带来的性能影响
七、总结
中介者模式是管理复杂对象交互的强大工具,特别适用于以下场景:
- 对象间存在大量直接连接
- 系统组件难以复用
- 交互逻辑分散难以理解
- 需要集中控制对象间通信
在C#中实现中介者模式时,可以:
- 定义清晰的中介者接口
- 使同事类只依赖于中介者
- 将复杂的交互逻辑封装在中介者中
- 考虑使用事件或委托简化实现
正确使用中介者模式可以显著降低系统复杂度,提高代码的可维护性和灵活性。
八、使用事件或委托简化实现中介者模式
中介者模式可以通过C#的事件和委托机制来简化实现,这种方式可以减少中介者类的复杂性,同时保持对象间的解耦。下面我将展示如何使用事件来重构中介者模式。
1. 基于事件的简化实现
基本架构
// 定义事件参数基类
public abstract class OrderEventArgs : EventArgs
{
public string EventType { get; set; }
}
// 库存系统事件参数
public class InventoryEventArgs : OrderEventArgs
{
public int ProductId { get; set; }
public int Quantity { get; set; }
}
// 支付系统事件参数
public class PaymentEventArgs : OrderEventArgs
{
public decimal Amount { get; set; }
public string PaymentMethod { get; set; }
}
// 订单组件基类(使用事件)
public abstract class OrderComponent
{
// 定义事件处理器委托
public delegate void OrderEventHandler(object sender, OrderEventArgs e);
// 组件事件
public event OrderEventHandler OnOrderEvent;
// 触发事件的方法
protected void RaiseEvent(OrderEventArgs e)
{
OnOrderEvent?.Invoke(this, e);
}
}
// 库存系统实现
public class InventorySystem : OrderComponent
{
public void CheckStock(int productId)
{
Console.WriteLine($"Checking stock for product {productId}...");
RaiseEvent(new InventoryEventArgs {
EventType = "StockChecked",
ProductId = productId,
Quantity = 100 // 假设检查到有100个库存
});
}
public void UpdateStock(int productId, int quantity)
{
Console.WriteLine($"Updating stock for product {productId}, quantity: {quantity}");
}
}
// 支付系统实现
public class PaymentSystem : OrderComponent
{
public void ProcessPayment(decimal amount, string method)
{
Console.WriteLine($"Processing payment of {amount} via {method}");
RaiseEvent(new PaymentEventArgs {
EventType = "PaymentProcessed",
Amount = amount,
PaymentMethod = method
});
}
}
事件协调器(轻量级中介者)
public class OrderEventCoordinator
{
private readonly InventorySystem _inventory;
private readonly PaymentSystem _payment;
public OrderEventCoordinator(InventorySystem inventory, PaymentSystem payment)
{
_inventory = inventory;
_payment = payment;
// 订阅库存系统事件
_inventory.OnOrderEvent += HandleInventoryEvent;
// 订阅支付系统事件
_payment.OnOrderEvent += HandlePaymentEvent;
}
private void HandleInventoryEvent(object sender, OrderEventArgs e)
{
if (e is InventoryEventArgs args && args.EventType == "StockChecked")
{
// 库存检查完成后处理支付
_payment.ProcessPayment(99.99m, "CreditCard");
}
}
private void HandlePaymentEvent(object sender, OrderEventArgs e)
{
if (e is PaymentEventArgs args && args.EventType == "PaymentProcessed")
{
// 支付完成后更新库存
_inventory.UpdateStock(1, -1); // 假设产品ID为1,减少1个库存
Console.WriteLine("Order completed!");
}
}
}
2. 使用Action委托的简化实现
更轻量的实现方式
// 组件基类(使用Action委托)
public abstract class OrderComponent
{
protected Action<string, object> MediatorCallback { get; }
public OrderComponent(Action<string, object> mediatorCallback)
{
MediatorCallback = mediatorCallback;
}
}
// 库存系统
public class InventorySystem : OrderComponent
{
public InventorySystem(Action<string, object> callback) : base(callback) {}
public void CheckStock(int productId)
{
Console.WriteLine($"Checking stock for product {productId}...");
MediatorCallback?.Invoke("StockChecked", new { ProductId = productId });
}
public void UpdateStock(int productId, int quantity)
{
Console.WriteLine($"Updating stock for product {productId}, quantity: {quantity}");
}
}
// 支付系统
public class PaymentSystem : OrderComponent
{
public PaymentSystem(Action<string, object> callback) : base(callback) {}
public void ProcessPayment(decimal amount, string method)
{
Console.WriteLine($"Processing payment of {amount} via {method}");
MediatorCallback?.Invoke("PaymentProcessed", new { Amount = amount, Method = method });
}
}
// 使用Lambda表达式作为中介者
public class Program
{
public static void Main()
{
// 创建支付系统并定义其回调
var payment = new PaymentSystem((eventType, data) =>
{
if (eventType == "PaymentProcessed")
{
Console.WriteLine("Payment processed callback");
}
});
// 创建库存系统并定义完整流程
var inventory = new InventorySystem((eventType, data) =>
{
dynamic eventData = data;
if (eventType == "StockChecked")
{
Console.WriteLine($"Stock checked for product {eventData.ProductId}");
payment.ProcessPayment(99.99m, "CreditCard");
}
else if (eventType == "PaymentProcessed")
{
inventory.UpdateStock(1, -1);
Console.WriteLine("Order completed!");
}
});
// 启动流程
inventory.CheckStock(1);
}
}
3. 使用.NET内置EventBus的简化实现
基于MediatR库的实现
// 安装MediatR NuGet包
// Install-Package MediatR
// 定义事件/通知
public class StockCheckedEvent : INotification
{
public int ProductId { get; set; }
}
public class PaymentProcessedEvent : INotification
{
public decimal Amount { get; set; }
}
// 定义处理器
public class StockCheckedHandler : INotificationHandler<StockCheckedEvent>
{
private readonly IMediator _mediator;
public StockCheckedHandler(IMediator mediator)
{
_mediator = mediator;
}
public async Task Handle(StockCheckedEvent notification, CancellationToken ct)
{
Console.WriteLine($"Stock checked for product {notification.ProductId}");
await _mediator.Publish(new PaymentProcessedEvent { Amount = 99.99m }, ct);
}
}
public class PaymentProcessedHandler : INotificationHandler<PaymentProcessedEvent>
{
public Task Handle(PaymentProcessedEvent notification, CancellationToken ct)
{
Console.WriteLine($"Payment processed: {notification.Amount}");
Console.WriteLine("Order completed!");
return Task.CompletedTask;
}
}
// 使用示例
var services = new ServiceCollection();
services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));
var provider = services.BuildServiceProvider();
var mediator = provider.GetRequiredService<IMediator>();
await mediator.Publish(new StockCheckedEvent { ProductId = 1 });
4. 比较与选择
| 实现方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 经典中介者模式 | 结构清晰,职责明确 | 中介者类可能变得庞大 | 复杂交互,需要集中控制 |
| 基于事件实现 | 松耦合,易于扩展 | 事件处理逻辑分散 | 组件间交互简单,需要灵活扩展 |
| Action委托回调 | 实现简单,轻量级 | 不适合复杂交互 | 简单流程,快速实现 |
| MediatR事件总线 | 专业解耦,支持异步 | 需要引入第三方库 | 企业级应用,需要强大事件处理 |
5. 最佳实践建议
- 简单场景:使用Action委托或简单事件实现
- 中等复杂度:使用基于事件的协调器模式
- 企业级应用:考虑使用MediatR等事件总线库
- 保持一致性:项目中统一使用一种实现方式
- 适度抽象:不要过度设计,根据实际需求选择
八、在Unity中的应用
示例1:UI系统管理
using UnityEngine;
using UnityEngine.UI;
// 中介者接口
public interface IUIMediator
{
void Notify(UIComponent sender, string eventName);
}
// 具体中介者 - UI管理器
public class UIManager : MonoBehaviour, IUIMediator
{
public Button startButton;
public Button optionsButton;
public Button quitButton;
public GameObject mainMenuPanel;
public GameObject optionsPanel;
private void Start()
{
// 为每个UI组件设置中介者引用
startButton.GetComponent<UIComponent>().SetMediator(this);
optionsButton.GetComponent<UIComponent>().SetMediator(this);
quitButton.GetComponent<UIComponent>().SetMediator(this);
// 初始化UI状态
mainMenuPanel.SetActive(true);
optionsPanel.SetActive(false);
}
// 处理UI组件通知
public void Notify(UIComponent sender, string eventName)
{
switch (eventName)
{
case "StartButtonClicked":
OnStartGame();
break;
case "OptionsButtonClicked":
OnOpenOptions();
break;
case "QuitButtonClicked":
OnQuitGame();
break;
case "BackButtonClicked":
OnBackToMenu();
break;
}
}
private void OnStartGame()
{
Debug.Log("开始游戏");
mainMenuPanel.SetActive(false);
// 这里可以添加游戏开始的逻辑
}
private void OnOpenOptions()
{
Debug.Log("打开选项菜单");
mainMenuPanel.SetActive(false);
optionsPanel.SetActive(true);
}
private void OnQuitGame()
{
Debug.Log("退出游戏");
Application.Quit();
}
private void OnBackToMenu()
{
Debug.Log("返回主菜单");
optionsPanel.SetActive(false);
mainMenuPanel.SetActive(true);
}
}
// 同事类 - UI组件基类
public class UIComponent : MonoBehaviour
{
protected IUIMediator mediator;
// 设置中介者
public void SetMediator(IUIMediator mediator)
{
this.mediator = mediator;
}
// 通知中介者
protected void NotifyMediator(string eventName)
{
mediator?.Notify(this, eventName);
}
}
// 具体同事类 - 开始按钮
public class StartButton : UIComponent
{
private Button button;
private void Awake()
{
button = GetComponent<Button>();
button.onClick.AddListener(OnClick);
}
private void OnClick()
{
NotifyMediator("StartButtonClicked");
}
}
// 具体同事类 - 选项按钮
public class OptionsButton : UIComponent
{
private Button button;
private void Awake()
{
button = GetComponent<Button>();
button.onClick.AddListener(OnClick);
}
private void OnClick()
{
NotifyMediator("OptionsButtonClicked");
}
}
// 具体同事类 - 退出按钮
public class QuitButton : UIComponent
{
private Button button;
private void Awake()
{
button = GetComponent<Button>();
button.onClick.AddListener(OnClick);
}
private void OnClick()
{
NotifyMediator("QuitButtonClicked");
}
}
// 具体同事类 - 返回按钮
public class BackButton : UIComponent
{
private Button button;
private void Awake()
{
button = GetComponent<Button>();
button.onClick.AddListener(OnClick);
}
private void OnClick()
{
NotifyMediator("BackButtonClicked");
}
}
示例2:游戏事件系统
using UnityEngine;
using System.Collections.Generic;
// 事件类型枚举
public enum GameEventType
{
PlayerDied,
EnemyKilled,
ItemCollected,
LevelCompleted
}
// 中介者接口
public interface IGameEventMediator
{
void Subscribe(GameEventType eventType, IGameEventSubscriber subscriber);
void Unsubscribe(GameEventType eventType, IGameEventSubscriber subscriber);
void Publish(GameEventType eventType, object sender, object eventData);
}
// 具体中介者 - 游戏事件管理器
public class GameEventManager : MonoBehaviour, IGameEventMediator
{
private Dictionary<GameEventType, List<IGameEventSubscriber>> subscribers =
new Dictionary<GameEventType, List<IGameEventSubscriber>>();
// 订阅事件
public void Subscribe(GameEventType eventType, IGameEventSubscriber subscriber)
{
if (!subscribers.ContainsKey(eventType))
{
subscribers[eventType] = new List<IGameEventSubscriber>();
}
if (!subscribers[eventType].Contains(subscriber))
{
subscribers[eventType].Add(subscriber);
}
}
// 取消订阅
public void Unsubscribe(GameEventType eventType, IGameEventSubscriber subscriber)
{
if (subscribers.ContainsKey(eventType))
{
subscribers[eventType].Remove(subscriber);
}
}
// 发布事件
public void Publish(GameEventType eventType, object sender, object eventData)
{
if (subscribers.ContainsKey(eventType))
{
foreach (var subscriber in subscribers[eventType])
{
subscriber.OnEvent(eventType, sender, eventData);
}
}
}
}
// 同事接口 - 事件订阅者
public interface IGameEventSubscriber
{
void OnEvent(GameEventType eventType, object sender, object eventData);
}
// 具体同事类 - 玩家控制器
public class PlayerController : MonoBehaviour, IGameEventSubscriber
{
private IGameEventMediator eventMediator;
public int health = 100;
private void Start()
{
eventMediator = FindObjectOfType<GameEventManager>();
eventMediator.Subscribe(GameEventType.PlayerDied, this);
}
private void OnDestroy()
{
eventMediator?.Unsubscribe(GameEventType.PlayerDied, this);
}
public void TakeDamage(int damage)
{
health -= damage;
if (health <= 0)
{
eventMediator.Publish(GameEventType.PlayerDied, this, null);
}
}
public void OnEvent(GameEventType eventType, object sender, object eventData)
{
if (eventType == GameEventType.PlayerDied && sender == this)
{
Debug.Log("玩家死亡事件处理");
// 处理玩家死亡逻辑
}
}
}
// 具体同事类 - 成就系统
public class AchievementSystem : MonoBehaviour, IGameEventSubscriber
{
private IGameEventMediator eventMediator;
private void Start()
{
eventMediator = FindObjectOfType<GameEventManager>();
eventMediator.Subscribe(GameEventType.EnemyKilled, this);
eventMediator.Subscribe(GameEventType.ItemCollected, this);
}
private void OnDestroy()
{
eventMediator?.Unsubscribe(GameEventType.EnemyKilled, this);
eventMediator?.Unsubscribe(GameEventType.ItemCollected, this);
}
public void OnEvent(GameEventType eventType, object sender, object eventData)
{
switch (eventType)
{
case GameEventType.EnemyKilled:
Debug.Log("成就系统: 敌人被击杀");
// 更新击杀成就
break;
case GameEventType.ItemCollected:
Debug.Log("成就系统: 物品被收集");
// 更新收集成就
break;
}
}
}
// 具体同事类 - 音频管理器
public class AudioManager : MonoBehaviour, IGameEventSubscriber
{
private IGameEventMediator eventMediator;
private void Start()
{
eventMediator = FindObjectOfType<GameEventManager>();
eventMediator.Subscribe(GameEventType.PlayerDied, this);
eventMediator.Subscribe(GameEventType.LevelCompleted, this);
}
private void OnDestroy()
{
eventMediator?.Unsubscribe(GameEventType.PlayerDied, this);
eventMediator?.Unsubscribe(GameEventType.LevelCompleted, this);
}
public void OnEvent(GameEventType eventType, object sender, object eventData)
{
switch (eventType)
{
case GameEventType.PlayerDied:
Debug.Log("播放死亡音效");
// 播放死亡音效
break;
case GameEventType.LevelCompleted:
Debug.Log("播放关卡完成音效");
// 播放胜利音效
break;
}
}
}
示例3:AI协调系统
using UnityEngine;
using System.Collections.Generic;
// 中介者接口
public interface IAIMediator
{
void RegisterAI(AIEntity ai);
void UnregisterAI(AIEntity ai);
void SendMessage(AIEntity sender, string message);
}
// 具体中介者 - AI协调器
public class AICoordinator : MonoBehaviour, IAIMediator
{
private List<AIEntity> aiEntities = new List<AIEntity>();
// 注册AI实体
public void RegisterAI(AIEntity ai)
{
if (!aiEntities.Contains(ai))
{
aiEntities.Add(ai);
}
}
// 注销AI实体
public void UnregisterAI(AIEntity ai)
{
aiEntities.Remove(ai);
}
// 广播消息
public void SendMessage(AIEntity sender, string message)
{
foreach (var ai in aiEntities)
{
if (ai != sender) // 不发送给自己
{
ai.ReceiveMessage(message);
}
}
}
}
// 同事类 - AI实体基类
public abstract class AIEntity : MonoBehaviour
{
protected IAIMediator mediator;
// 设置中介者
public void SetMediator(IAIMediator mediator)
{
this.mediator = mediator;
mediator.RegisterAI(this);
}
// 发送消息
protected void SendToOthers(string message)
{
mediator?.SendMessage(this, message);
}
// 接收消息
public abstract void ReceiveMessage(string message);
private void OnDestroy()
{
mediator?.UnregisterAI(this);
}
}
// 具体同事类 - 守卫AI
public class GuardAI : AIEntity
{
private bool isAlerted = false;
private void Start()
{
// 在中介者中注册
SetMediator(FindObjectOfType<AICoordinator>());
}
// 发现玩家
public void SpotPlayer()
{
Debug.Log("守卫发现玩家!");
isAlerted = true;
SendToOthers("PlayerSpotted");
}
// 接收消息
public override void ReceiveMessage(string message)
{
if (message == "PlayerSpotted" && !isAlerted)
{
Debug.Log("守卫收到警报: 玩家被发现!");
isAlerted = true;
// 进入警戒状态
}
}
}
// 具体同事类 - 巡逻AI
public class PatrolAI : AIEntity
{
private bool isAlerted = false;
private void Start()
{
// 在中介者中注册
SetMediator(FindObjectOfType<AICoordinator>());
}
// 发现玩家
public void SpotPlayer()
{
Debug.Log("巡逻AI发现玩家!");
isAlerted = true;
SendToOthers("PlayerSpotted");
}
// 接收消息
public override void ReceiveMessage(string message)
{
if (message == "PlayerSpotted" && !isAlerted)
{
Debug.Log("巡逻AI收到警报: 玩家被发现!");
isAlerted = true;
// 改变巡逻路线
}
}
}
// 具体同事类 - 狙击手AI
public class SniperAI : AIEntity
{
private bool isAlerted = false;
private void Start()
{
// 在中介者中注册
SetMediator(FindObjectOfType<AICoordinator>());
}
// 接收消息
public override void ReceiveMessage(string message)
{
if (message == "PlayerSpotted" && !isAlerted)
{
Debug.Log("狙击手收到警报: 玩家被发现!准备狙击...");
isAlerted = true;
// 进入狙击位置
}
}
}
在Unity中的实现建议
- 使用ScriptableObject:可以将中介者实现为ScriptableObject,便于在编辑器中配置
- 与事件系统结合:Unity自身的EventSystem也可以看作是一种中介者模式的实现
- 考虑性能:对于高频交互,注意中介者可能成为性能瓶颈
- 避免过度使用:不是所有对象交互都需要中介者,简单交互可以直接通信
- 分层设计:可以为不同子系统设计不同的中介者,避免单个中介者过于复杂
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
