Skip to content

中介者模式

让多个对象不再“互相通知”,而是都交给“中介者”去协调消息和命令

“大家都找老大,老大来指挥”

适合的场景

  • 系统中多个对象之间关系复杂、交互频繁

  • 对象之间直接引用彼此导致强耦合,修改一个就要改一堆

  • 想要把对象之间的“通信逻辑”集中管理,让每个对象专注于自己的本职工作

比如 UI 按钮控制输入框状态、聊天室中的多个用户都通过服务器中介通信,或者是角色状态机里不同模块之间解耦交互~都会用到它

基本结构

  • Mediator 中介者接口

  • ConcreteMediator 具体中介者,实现协调逻辑

  • Colleague 同事对象,持有对中介者的引用,只跟中介者通信

示例

C# 聊天系统

csharp
// 中介者接口
interface IChatMediator 
{
    void SendMessage(string message, User user);
}

// 具体中介者
class ChatRoom : IChatMediator 
{
    private List<User> users = new();

    public void Register(User user) 
    {
        users.Add(user);
    }

    public void SendMessage(string message, User sender) 
    {
        foreach (var user in users) 
        {
            if (user != sender) 
            {
                user.Receive(message);
            }
        }
    }
}

// 同事类
class User 
{
    private readonly string _name;
    private readonly IChatMediator _mediator;

    public User(string name, IChatMediator mediator) 
    {
        _name = name;
        _mediator = mediator;
    }

    public void Send(string message) 
    {
        Console.WriteLine($"{_name} 发送: {message}");
        _mediator.SendMessage(message, this);
    }

    public void Receive(string message) 
    {
        Console.WriteLine($"{_name} 收到: {message}");
    }
}

// 使用
var chatRoom = new ChatRoom();
var inabaMeguru= new User("Inaba Meguru", chatRoom);
var ayachiNene= new User("Ayachi Nene", chatRoom);
chatRoom.Register(inabaMeguru);
chatRoom.Register(ayachiNene);

inabaMeguru.Send("Ciallo~(∠・▽< )⌒☆");

GDScript示例

UI控件中介

gdscript
class Mediator:

    func notify(sender: Node, event: String) -> void:
        pass 

class DialogMediator extends Mediator:

    var button_close
    var label_info

    func _init(close_btn: Button, label: Label):
        button_close = close_btn
        label_info = label

    func notify(sender: Node, event: String) -> void:       
        if sender == button_close and event == "click":         
            label_info.text = "按钮被禁用"
            button_close.disabled = true

# 使用时
func _ready():
    var cloneButton := Button.new()
    cloneButton.size = Vector2(128, 128)
    cloneButton.text = "点我"
    add_child(cloneButton)

    var infoLabel := Label.new()
    infoLabel.text = "点击禁用按钮"
    add_child(infoLabel)

    var mediator = DialogMediator.new(cloneButton, infoLabel)
    cloneButton.pressed.connect(func(): mediator.notify(cloneButton, "click"))