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(); // 窗帘也会收到通知

✅ 优点

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

❌ 缺点

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

📊 与其他模式对比

模式 区别
观察者模式 观察者是一对多广播,中介者是多对多协调
外观模式 外观简化子系统接口,中介者协调对象交互
命令模式 命令封装请求,中介者协调通信
相关推荐
victory_li2 小时前
OpenVINO + Yolov26 + C# + .net framework4.8实现分类推理
yolo·c#·openvino
吴爃2 小时前
Logstash WebHDFS 异常导致历史日志补读与 OOM
c#·linq
WarPigs2 小时前
C# EntityFramework笔记
数据库·c#
thisiszdy2 小时前
<C++&C#> lambda表达式
java·c++·c#
咖啡八杯2 小时前
GoF设计模式——外观模式
java·设计模式·外观模式
叶帆3 小时前
【YFIOs】用C#开发硬件之串口通信
开发语言·c#
江湖中的阿龙3 小时前
23种设计模式
java·开发语言·设计模式
xiaoshuaishuai83 小时前
C# Avaloniaui ListBox样式及用法
开发语言·c#
basketball6163 小时前
设计模式入门:7. 策略模式详解 C++实现
c++·设计模式·策略模式