18. 中介者模式(Mediator Pattern)

18. 中介者模式(Mediator Pattern)

分类 : 行为型模式

热门度 : ★★★☆☆

难度: ★★★☆☆


📖 概念

中介者模式定义一个中介对象来封装一组对象之间的交互,使各对象不需要显式地相互引用,从而降低耦合度。

🎯 意图

将多对多的网状交互转换为一对多的星型交互,所有同事对象通过中介者通信。

🔑 关键角色

角色 说明
IMediator(中介者接口) 定义通信接口
ConcreteMediator(具体中介者) 协调各同事对象的交互
Colleague(同事对象) 通过中介者与其他同事通信

⚠️ 注意事项

  • 中介者可能变得过于复杂(上帝对象)
  • 适合交互关系复杂的场景,简单场景不必使用
  • C# 中可结合事件机制实现松耦合

🔄 实现流程

复制代码
1. 定义中介者接口
2. 创建具体中介者,持有所有同事引用
3. 同事对象持有中介者引用
4. 同事间通过中介者转发消息

💡 常见使用场景

场景1: 聊天室消息转发

csharp 复制代码
// 中介者接口
public interface IChatMediator
{
    void SendMessage(string message, User sender);
    void RegisterUser(User user);
}

// 同事基类
public abstract class User
{
    protected IChatMediator _mediator;
    public string Name { get; set; }
    protected User(IChatMediator mediator, string name)
    { _mediator = mediator; Name = name; }
    public abstract void Send(string message);
    public abstract void Receive(string message);
}

// 具体中介者 - 聊天室
public class ChatRoom : IChatMediator
{
    private Dictionary<string, User> _users = new();
    public void RegisterUser(User user) => _users[user.Name] = user;
    public void SendMessage(string message, User sender)
    {
        foreach (var user in _users.Values)
            if (user != sender) user.Receive($"[{sender.Name}]: {message}");
    }
}

// 具体同事
public class ChatUser : User
{
    public ChatUser(IChatMediator mediator, string name) : base(mediator, name) { }
    public override void Send(string message) => _mediator.SendMessage(message, this);
    public override void Receive(string message) => Console.WriteLine($"{Name} 收到: {message}");
}

// 使用
var chatRoom = new ChatRoom();
var alice = new ChatUser(chatRoom, "Alice");
var bob = new ChatUser(chatRoom, "Bob");
var charlie = new ChatUser(chatRoom, "Charlie");
chatRoom.RegisterUser(alice);
chatRoom.RegisterUser(bob);
chatRoom.RegisterUser(charlie);
alice.Send("大家好!"); // Bob 和 Charlie 都收到

场景2: 表单字段联动

csharp 复制代码
// 中介者接口
public interface IFormMediator
{
    void ValueChanged(string fieldName, string value);
}

// 具体中介者 - 注册表单
public class RegistrationFormMediator : IFormMediator
{
    private CountryDropdown _country;
    private CityDropdown _city;
    private PhoneInput _phone;
    private SubmitButton _submit;

    public RegistrationFormMediator()
    {
        _country = new CountryDropdown(this);
        _city = new CityDropdown(this);
        _phone = new PhoneInput(this);
        _submit = new SubmitButton(this);
    }

    public void ValueChanged(string fieldName, string value)
    {
        switch (fieldName)
        {
            case "country":
                Console.WriteLine($"[中介者] 国家变更为 {value},更新城市列表和区号");
                _city.UpdateCities(value);
                _phone.UpdateCountryCode(value);
                break;
            case "city":
                Console.WriteLine($"[中介者] 城市变更为 {value},检查表单完整性");
                break;
            case "phone":
                Console.WriteLine($"[中介者] 电话变更,验证格式");
                _submit.SetEnabled(!string.IsNullOrEmpty(value));
                break;
        }
    }

    public void Simulate() { _country.Select("中国"); _phone.SetPhone("13800138000"); }
}

// 同事类
public class CountryDropdown
{
    private IFormMediator _mediator;
    public CountryDropdown(IFormMediator mediator) { _mediator = mediator; }
    public void Select(string country) { Console.WriteLine($"选择国家: {country}"); _mediator.ValueChanged("country", country); }
}

public class CityDropdown
{
    private IFormMediator _mediator;
    public CityDropdown(IFormMediator mediator) { _mediator = mediator; }
    public void UpdateCities(string country) => Console.WriteLine($"更新城市列表: {country} 的城市");
}

public class PhoneInput
{
    private IFormMediator _mediator;
    public PhoneInput(IFormMediator mediator) { _mediator = mediator; }
    public void SetPhone(string phone) { Console.WriteLine($"输入电话: {phone}"); _mediator.ValueChanged("phone", phone); }
    public void UpdateCountryCode(string country) => Console.WriteLine($"更新区号: {country}");
}

public class SubmitButton
{
    private IFormMediator _mediator;
    public SubmitButton(IFormMediator mediator) { _mediator = mediator; }
    public void SetEnabled(bool enabled) => Console.WriteLine($"提交按钮: {(enabled ? "可用" : "禁用")}");
}

// 使用
var form = new RegistrationFormMediator();
form.Simulate();

场景3: 智能家居设备协调

csharp 复制代码
public interface IHomeMediator
{
    void Notify(string source, string @event);
}

public class SmartHomeHub : IHomeMediator
{
    private Dictionary<string, Action<string>> _handlers = new();
    public void Register(string device, Action<string> handler) => _handlers[device] = handler;
    public void Notify(string source, string @event)
    {
        Console.WriteLine($"[中枢] {source} 触发: {@event}");
        foreach (var handler in _handlers)
            if (handler.Key != source) handler.Value($"{source}:{@event}");
    }
}

public class SmartLight
{
    private string _name;
    private IHomeMediator _mediator;
    public SmartLight(string name, IHomeMediator mediator) { _name = name; _mediator = mediator; }
    public void TurnOn() { Console.WriteLine($"{_name} 灯打开"); _mediator.Notify(_name, "on"); }
    public void OnEvent(string e) => Console.WriteLine($"{_name} 收到事件: {e}");
}

public class SmartCurtain
{
    private string _name;
    private IHomeMediator _mediator;
    public SmartCurtain(string name, IHomeMediator mediator) { _name = name; _mediator = mediator; }
    public void Open() { Console.WriteLine($"{_name} 窗帘打开"); _mediator.Notify(_name, "open"); }
    public void OnEvent(string e) => Console.WriteLine($"{_name} 收到事件: {e}");
}

// 使用
var hub = new SmartHomeHub();
var light = new SmartLight("客厅灯", hub);
var curtain = new SmartCurtain("客厅窗帘", hub);
hub.Register("客厅灯", light.OnEvent);
hub.Register("客厅窗帘", curtain.OnEvent);
light.TurnOn(); // 窗帘也会收到通知

✅ 优点

  • 降低同事对象之间的耦合
  • 将多对多交互转为一对多
  • 符合迪米特原则

❌ 缺点

  • 中介者可能变得过于复杂
  • 中介者承担过多职责时难以维护

📊 与其他模式对比

模式 区别
观察者模式 观察者是一对多广播,中介者是多对多协调
外观模式 外观简化子系统接口,中介者协调对象交互
命令模式 命令封装请求,中介者协调通信
相关推荐
周杰伦fans2 小时前
8GB显存下模型量化实战指南
人工智能·后端·c#
samble4 小时前
从零搭建灌装监控系统(十二):配置系统,原子写入与容错
c#·wpf·mvvm·modbus·工业控制
晚安code7 小时前
设计模式入门:吃透 SOLID 原则与迪米特法则,再学 5 个高频模式
后端·设计模式
流形填表7 小时前
题库去重实战:基于题干指纹的重复题清理
开发语言·c#
染指111010 小时前
135.Agent-多Agent框架-LangChain多智能体(SubAgents子代理)
数据库·人工智能·设计模式·langchain·agent·agents
开开心心就好13 小时前
以图搜图找重复图片,本地工具离线就能用
javascript·智能手机·ffmpeg·c#·ocr·word·音视频
QQ_216962909613 小时前
基于C#(Asp.net)电竞陪玩信息管理系统的设计与实现
java·大数据·spring boot·微信小程序·c#·云计算·asp.net
未来之窗软件服务1 天前
C# 截图源码支持自动保存-东方仙盟
c#·仙盟创梦ide·东方仙盟·电脑工具
路弥行至1 天前
【Head First 设计模式】第 2 章:观察者模式 —— 用现代 C++ 重新解读“交互对象的松耦合
c++·经验分享·笔记·观察者模式·设计模式·入门教程·headfirst
YYYing.1 天前
【设计模式系列 (九) 】装饰器模式
c++·后端·设计模式·装饰器模式·c/c++