C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C#和Unity中的中介者模式

C#和Unity中的中介者模式使用方式

作者:_克克克

中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性

C#中的中介者模式详解

中介者模式(Mediator Pattern)是一种行为设计模式,它能减少对象之间混乱无序的依赖关系,通过引入一个中介者对象来封装一系列对象之间的交互。

一、中介者模式的基本概念

1. 定义

中介者模式定义了一个对象来封装一组对象之间的交互方式,使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

2. 组成要素

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. 典型使用场景

  1. 对象间存在复杂的引用关系:当系统中对象之间存在复杂的网状引用关系,导致系统结构混乱且难以理解时。
  2. 需要集中控制对象间的交互:当多个类之间有复杂的交互逻辑,且这些逻辑需要集中管理时。
  3. 想定制分布在多个类中的行为:当行为分布在多个类中,但又需要根据需求改变这些行为时。
  4. GUI组件交互:图形用户界面中,各种控件(按钮、文本框等)之间的交互。
  5. 消息传递系统:如聊天应用、通知系统等需要多方通信的场景。

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#中实现中介者模式时,可以:

  1. 定义清晰的中介者接口
  2. 使同事类只依赖于中介者
  3. 将复杂的交互逻辑封装在中介者中
  4. 考虑使用事件或委托简化实现

正确使用中介者模式可以显著降低系统复杂度,提高代码的可维护性和灵活性。

八、使用事件或委托简化实现中介者模式

中介者模式可以通过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. 最佳实践建议

  1. 简单场景:使用Action委托或简单事件实现
  2. 中等复杂度:使用基于事件的协调器模式
  3. 企业级应用:考虑使用MediatR等事件总线库
  4. 保持一致性:项目中统一使用一种实现方式
  5. 适度抽象:不要过度设计,根据实际需求选择

八、在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中的实现建议

  1. 使用ScriptableObject:可以将中介者实现为ScriptableObject,便于在编辑器中配置
  2. 与事件系统结合:Unity自身的EventSystem也可以看作是一种中介者模式的实现
  3. 考虑性能:对于高频交互,注意中介者可能成为性能瓶颈
  4. 避免过度使用:不是所有对象交互都需要中介者,简单交互可以直接通信
  5. 分层设计:可以为不同子系统设计不同的中介者,避免单个中介者过于复杂

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文