1. 介绍
中介模式定义了一个单独的(中介)对象,来封装一组对象之间的交互。将这组对象之间的交互委派给与中介对象交互,来避免对象之间的直接交互。
中介模式的设计思想跟中间层很像,通过引入中介这个中间层,将一组对象之间的交互关系(或者依赖关系)从多对多(网状关系)转换为一对多(星状关系)。原来一个对象要跟 n 个对象交互,现在只需要跟一个中介对象交互,从而最小化对象之间的交互关系,降低了代码的复杂度,提高了代码的可读性和可维护性。
观察者模式和中介模式都是为了实现参与者之间的解耦,简化交互关系。两者的不同在于应用场景上。在观察者模式的应用场景中,参与者之间的交互比较有条理,一般都是单向的,一个参与者只有一个身份,要么是观察者,要么是被观察者。而在中介模式的应用场景中,参与者之间的交互关系错综复杂,既可以是消息的发送者、也可以同时是消息的接收者。
2. 核心思想
解耦直接交互:将对象间的网状交互关系改为星型结构
集中控制:所有交互逻辑集中在中介者中
简化对象职责:对象只需与中介者通信,无需了解其他对象
3. 结构组成
Mediator(中介者接口):定义同事对象到中介者的接口
ConcreteMediator(具体中介者):协调各同事对象的交互
Colleague(同事类):知道其中介者对象,与其他同事通信时通过中介者
4. 游戏开发中典型应用
聊天系统(如上文示例)
游戏事件系统
UI管理系统
多人游戏中的网络消息转发
游戏对象间的交互协调
5. 代码示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace DesignPatternsPractice.Src.Behavioral.MediatorDesignPattern
{
/// <summary>
/// 中介者模式
/// 实现一个玩家的聊天系统
/// </summary>
public class MediatorDesignPattern
{
static void Main()
{
Mediator mediator = new Mediator();
// 创建玩家并加入聊天室
Player player1 = new Player(mediator, "001");
Player player2 = new Player(mediator, "002");
Player player3 = new Player(mediator, "003");
mediator.AddPlayer(player1);
mediator.AddPlayer(player2);
mediator.AddPlayer(player3);
player1.sendMessage("大家好");
}
}
/// <summary>
/// 抽象中介者
/// </summary>
public interface IMediator
{
void sendMessage(string message,Player player);
void AddPlayer(Player player);
}
/// <summary>
/// 具体中介者
/// </summary>
public class Mediator : IMediator
{
private List<Player> _players = new List<Player>();
public void AddPlayer(Player player)
{
_players.Add(player);
}
public void sendMessage(string message,Player player)
{
foreach (var item in _players)
{
// 防止发给自己
if (player != item)
item.AcceptMessage(message);
}
}
}
public abstract class IPlayer
{
public Mediator _mediator;
public string _Name { get; }
public IPlayer(Mediator mediator, string name)
{
_mediator = mediator;
_Name = name;
}
/// <summary>
/// 接收消息
/// </summary>
/// <param name="message"></param>
public abstract void AcceptMessage(string message);
/// <summary>
/// 发送消息
/// </summary>
/// <param name="message"></param>
public abstract void sendMessage(string message);
}
public class Player : IPlayer
{
public Player(Mediator mediator, string name) : base(mediator, name)
{
}
public override void AcceptMessage(string message)
{
Console.WriteLine($"{_Name}:收到了消息-->{message}");
}
public override void sendMessage(string message)
{
_mediator.sendMessage(message, this);
}
}
}