中介者模式

在软件系统开发中,当多个对象存在频繁且复杂的交互时,对象间直接两两通信会形成紧密耦合的“网状依赖”,导致代码可读性差、维护成本高、扩展难度大。中介者模式(Mediator Pattern)作为经典的行为型设计模式,核心是引入中介者对象封装多对象交互逻辑,使所有对象仅与中介者通信、无需直接关联,将“网状交互”转化为“星型交互”,大幅降低系统耦合度,提升代码可维护性与可扩展性。本文将深入剖析中介者模式的核心结构,通过C#、Python、Go、C++、纯C多语言落地实现,拆解其优缺点与适用场景,总结设计精髓与工程实践要点。

一、中介者模式核心结构

中介者模式的核心是分离交互逻辑与业务逻辑,由中介者承担对象间的通信协调职责,让同事类专注于自身核心业务。其核心角色分为四类,职责分工明确,完整覆盖“交互协调-业务执行”全流程:

1.1 抽象中介者(Mediator)

定义中介者与同事类的通信接口,是两者交互的行为契约。通常包含两大核心方法:一是注册同事类,将同事对象纳入中介者管理范围;二是转发交互请求,将一个同事的请求传递给其他相关同事,无需关注具体交互逻辑的实现。

1.2 具体中介者(ConcreteMediator)

抽象中介者的具体实现,是整个模式的核心协调者。它维护所有同事类的引用,封装具体交互规则,接收同事类的请求并按业务逻辑转发给对应同事,实现多对象协同交互。同时,具体中介者可承载自身业务逻辑,进一步简化同事类职责。

1.3 抽象同事类(Colleague)

定义所有同事类的通用接口,封装共性行为。它持有抽象中介者的引用,使同事类可通过中介者与其他同事通信,无需直接引用。抽象同事类通常包含发送请求和接收请求的抽象方法,由具体同事类实现。

1.4 具体同事类(ConcreteColleague)

抽象同事类的具体实现,是业务逻辑的载体。它实现自身核心业务逻辑,与其他同事交互时,不直接调用对方方法,而是通过中介者转发请求;同时接收中介者转发的请求,执行相应处理逻辑。

核心逻辑链路:具体同事类 → 发送请求至中介者 → 具体中介者解析交互规则 → 转发请求至相关同事类 → 接收请求的同事类执行处理。全程同事类无直接交互,完全通过中介者完成通信。

二、多语言实现中介者模式

为便于开发者落地实践,本文以“在线聊天室”为经典案例,统一实现中介者模式:多个用户(具体同事类)通过聊天室(具体中介者)发送、接收消息,无需直接建立通信,仅需将消息发送至聊天室,由其统一转发给其他在线用户。所有实现均保证可运行,贴合各语言设计理念,补充规范注释、异常处理与边界判断,兼顾实用性与可读性,体现各语言对中介者模式的适配思路。

2.1 C# 实现(依托接口,贴合面向对象规范)

C# 作为强类型面向对象语言,通过接口严格定义抽象中介者与同事类的契约,利用泛型和集合优化同事类管理,依托GC自动管理内存,代码结构严谨、可读性高,适配企业级业务系统,是中介者模式的常用实现方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
using System;
using System.Collections.Generic;

/// <summary>
/// 抽象中介者:聊天室接口,定义中介者与用户的通信契约
/// </summary>
public interface IChatRoomMediator
{
/// <summary>
/// 注册用户(将用户纳入聊天室管理)
/// </summary>
/// <param name="user">用户实例</param>
void RegisterUser(User user);

/// <summary>
/// 转发消息(将发送者的消息转发给其他所有用户)
/// </summary>
/// <param name="message">消息内容</param>
/// <param name="sender">消息发送者</param>
void SendMessage(string message, User sender);
}

/// <summary>
/// 具体中介者:在线聊天室,实现消息转发和用户管理逻辑
/// </summary>
public class ChatRoom : IChatRoomMediator
{
// 存储在线用户列表,线程安全考虑,使用锁机制
private readonly List<User> _users = new List<User>();
private readonly object _lockObj = new object();

public void RegisterUser(User user)
{
if (user == null)
throw new ArgumentNullException(nameof(user), "用户实例不可为null");

lock (_lockObj)
{
if (!_users.Contains(user))
{
_users.Add(user);
user.Mediator = this; // 为用户绑定中介者
Console.WriteLine($"用户【{user.Name}】加入聊天室");
}
}
}

public void SendMessage(string message, User sender)
{
if (sender == null)
throw new ArgumentNullException(nameof(sender), "发送者实例不可为null");
if (string.IsNullOrEmpty(message))
throw new ArgumentException("消息内容不可为空或空白", nameof(message));

lock (_lockObj)
{
// 遍历所有在线用户,转发消息(发送者不接收自己的消息)
foreach (var user in _users)
{
if (user != sender)
{
user.ReceiveMessage(message, sender.Name);
}
}
}
}
}

/// <summary>
/// 抽象同事类:用户,定义用户的通用行为
/// </summary>
public abstract class User
{
/// <summary>
/// 用户名
/// </summary>
public string Name { get; }

/// <summary>
/// 关联的中介者(聊天室)
/// </summary>
public IChatRoomMediator Mediator { get; set; }

public User(string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentException("用户名不可为空或空白");
Name = name;
}

/// <summary>
/// 发送消息(通过中介者转发)
/// </summary>
/// <param name="message">消息内容</param>
public abstract void SendMessage(string message);

/// <summary>
/// 接收消息(处理中介者转发的消息)
/// </summary>
/// <param name="message">消息内容</param>
/// <param name="senderName">发送者用户名</param>
public abstract void ReceiveMessage(string message, string senderName);
}

/// <summary>
/// 具体同事类:普通用户,实现用户的发送和接收消息逻辑
/// </summary>
public class NormalUser : User
{
public NormalUser(string name) : base(name) { }

public override void SendMessage(string message)
{
if (Mediator == null)
throw new InvalidOperationException("用户未加入任何聊天室,无法发送消息");

Console.WriteLine($"\n{Name} 发送消息:{message}");
Mediator.SendMessage(message, this); // 通过中介者转发消息
}

public override void ReceiveMessage(string message, string senderName)
{
Console.WriteLine($"{Name} 收到 {senderName} 的消息:{message}");
}
}

// 客户端测试代码
class Program
{
static void Main(string[] args)
{
try
{
// 1. 初始化中介者(聊天室)
IChatRoomMediator chatRoom = new ChatRoom();

// 2. 初始化具体同事类(用户)
User user1 = new NormalUser("张三");
User user2 = new NormalUser("李四");
User user3 = new NormalUser("王五");

// 3. 注册用户到聊天室(绑定中介者)
chatRoom.RegisterUser(user1);
chatRoom.RegisterUser(user2);
chatRoom.RegisterUser(user3);

// 4. 模拟用户发送消息,测试中介者转发逻辑
user1.SendMessage("大家好!我是张三,很高兴加入聊天室~");
Console.WriteLine("---");
user2.SendMessage("张三你好!欢迎加入~");
Console.WriteLine("---");
user3.SendMessage("大家好呀!");
}
catch (Exception ex)
{
Console.WriteLine($"C# 执行异常:{ex.Message}");
}
}
}

2.2 Python 实现(动态语言特性,简洁灵活)

Python 遵循“鸭子类型”,无需显式定义抽象接口,通过基类约定中介者与同事类的行为,语法简洁、无需繁琐类型声明,依托GC自动管理内存,适配快速开发、脚本开发及轻量级项目,完整保留“解耦交互”核心逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class ChatRoomMediator:
"""抽象中介者:聊天室基类,约定中介者的核心行为"""
def register_user(self, user):
"""注册用户
Args:
user (User): 用户实例
"""
raise NotImplementedError("具体中介者需实现register_user方法")

def send_message(self, message, sender):
"""转发消息
Args:
message (str): 消息内容
sender (User): 消息发送者
"""
raise NotImplementedError("具体中介者需实现send_message方法")

class ConcreteChatRoom(ChatRoomMediator):
"""具体中介者:在线聊天室,实现用户管理和消息转发逻辑"""
def __init__(self):
self.users = [] # 存储在线用户列表

def register_user(self, user):
if user is None:
raise ValueError("用户实例不可为None")
if user not in self.users:
self.users.append(user)
user.mediator = self # 为用户绑定中介者
print(f"用户【{user.name}】加入聊天室")

def send_message(self, message, sender):
if sender is None:
raise ValueError("发送者实例不可为None")
if not message or message.strip() == "":
raise ValueError("消息内容不可为空或空白")
# 转发消息,发送者不接收自己的消息
for user in self.users:
if user != sender:
user.receive_message(message, sender.name)

class User:
"""抽象同事类:用户基类,约定用户的核心行为"""
def __init__(self, name):
if not name or name.strip() == "":
raise ValueError("用户名不可为空或空白")
self.name = name
self.mediator = None # 关联的中介者(初始为None)

def send_message(self, message):
"""发送消息(通过中介者转发)"""
raise NotImplementedError("具体用户需实现send_message方法")

def receive_message(self, message, sender_name):
"""接收消息(处理中介者转发的消息)"""
raise NotImplementedError("具体用户需实现receive_message方法")

class NormalUser(User):
"""具体同事类:普通用户,实现发送和接收消息的具体逻辑"""
def send_message(self, message):
if self.mediator is None:
raise RuntimeError("用户未加入任何聊天室,无法发送消息")
print(f"\n{self.name} 发送消息:{message}")
self.mediator.send_message(message, self) # 通过中介者转发消息

def receive_message(self, message, sender_name):
print(f"{self.name} 收到 {sender_name} 的消息:{message}")

# 客户端测试代码
if __name__ == "__main__":
try:
# 初始化中介者和用户
chat_room = ConcreteChatRoom()
user1 = NormalUser("张三")
user2 = NormalUser("李四")
user3 = NormalUser("王五")

# 注册用户到聊天室
chat_room.register_user(user1)
chat_room.register_user(user2)
chat_room.register_user(user3)

# 模拟用户发送消息
user1.send_message("大家好!我是张三,很高兴加入聊天室~")
print("---")
user2.send_message("张三你好!欢迎加入~")
print("---")
user3.send_message("大家好呀!")
except Exception as e:
print(f"Python 执行异常:{str(e)}")

2.3 Go 实现(接口至上,轻量化解耦)

Go 语言无类和继承,核心遵循“组合优于继承”,通过接口定义中介者与同事类的统一契约,结构体实现具体逻辑,代码极简高效,贴合Go“简洁、务实、高性能”的设计理念,适配高并发后端开发场景。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main

import (
"fmt"
"sync"
)

// 抽象中介者接口:定义聊天室的核心行为
type ChatRoomMediator interface {
RegisterUser(user User) // 注册用户
SendMessage(message string, sender User) // 转发消息
}

// 具体中介者:在线聊天室
type ConcreteChatRoom struct {
users []User // 在线用户列表
mu sync.RWMutex // 读写锁,保证并发安全
}

// NewConcreteChatRoom 工厂函数:创建聊天室实例
func NewConcreteChatRoom() *ConcreteChatRoom {
return &ConcreteChatRoom{
users: make([]User, 0),
}
}

// RegisterUser 实现注册用户逻辑
func (c *ConcreteChatRoom) RegisterUser(user User) {
if user == nil {
fmt.Println("Golang: 用户实例不可为nil")
return
}
c.mu.Lock()
defer c.mu.Unlock()
// 避免重复注册
for _, u := range c.users {
if u == user {
return
}
}
c.users = append(c.users, user)
user.SetMediator(c) // 为用户绑定中介者
fmt.Printf("用户【%s】加入聊天室\n", user.GetName())
}

// SendMessage 实现消息转发逻辑
func (c *ConcreteChatRoom) SendMessage(message string, sender User) {
if sender == nil {
fmt.Println("Golang: 发送者实例不可为nil")
return
}
if message == "" {
fmt.Println("Golang: 消息内容不可为空")
return
}
c.mu.RLock()
defer c.mu.RUnlock()
// 转发消息,发送者不接收自己的消息
for _, user := range c.users {
if user != sender {
user.ReceiveMessage(message, sender.GetName())
}
}
}

// 抽象同事类接口:定义用户的核心行为
type User interface {
GetName() string // 获取用户名
SetMediator(mediator ChatRoomMediator) // 绑定中介者
SendMessage(message string) // 发送消息
ReceiveMessage(message string, senderName string) // 接收消息
}

// 具体同事类:普通用户
type NormalUser struct {
name string
mediator ChatRoomMediator
}

// NewNormalUser 工厂函数:创建普通用户实例
func NewNormalUser(name string) *NormalUser {
if name == "" {
fmt.Println("Golang: 用户名不可为空")
return nil
}
return &NormalUser{
name: name,
}
}

func (u *NormalUser) GetName() string {
return u.name
}

func (u *NormalUser) SetMediator(mediator ChatRoomMediator) {
u.mediator = mediator
}

func (u *NormalUser) SendMessage(message string) {
if u.mediator == nil {
fmt.Printf("Golang: 用户【%s】未加入任何聊天室,无法发送消息\n", u.name)
return
}
fmt.Printf("\n%s 发送消息:%s\n", u.name, message)
u.mediator.SendMessage(message, u) // 通过中介者转发消息
}

func (u *NormalUser) ReceiveMessage(message string, senderName string) {
fmt.Printf("%s 收到 %s 的消息:%s\n", u.name, senderName, message)
}

// 客户端测试代码
func main() {
// 初始化中介者(聊天室)
chatRoom := NewConcreteChatRoom()
// 初始化具体同事类(用户)
user1 := NewNormalUser("张三")
user2 := NewNormalUser("李四")
user3 := NewNormalUser("王五")

// 注册用户到聊天室
chatRoom.RegisterUser(user1)
chatRoom.RegisterUser(user2)
chatRoom.RegisterUser(user3)

// 模拟用户发送消息
user1.SendMessage("大家好!我是张三,很高兴加入聊天室~")
fmt.Println("---")
user2.SendMessage("张三你好!欢迎加入~")
fmt.Println("---")
user3.SendMessage("大家好呀!")
}

2.4 C++ 实现(抽象类+多态,经典面向对象实现)

C++ 作为经典面向对象语言,通过抽象类(纯虚函数)定义中介者与同事类的接口,子类实现具体逻辑,依托继承和多态特性实现解耦,需手动管理内存(通过析构函数释放对象),兼顾灵活性与高性能,适配底层开发、高频调用场景,是底层系统、高性能应用的优选实现方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <iostream>
#include <vector>
#include <string>
#include <mutex>
using namespace std;

// 前向声明:解决同事类与中介者的交叉引用问题
class User;

// 抽象中介者类(纯虚函数定义接口)
class ChatRoomMediator {
public:
virtual ~ChatRoomMediator() = default; // 虚析构函数,避免多态场景内存泄漏
/// <summary>
/// 注册用户
/// </summary>
/// <param name="user">用户指针</param>
virtual void registerUser(User* user) = 0;
/// <summary>
/// 转发消息
/// </summary>
/// <param name="message">消息内容</param>
/// <param name="sender">消息发送者指针</param>
virtual void sendMessage(const string& message, User* sender) = 0;
};

// 抽象同事类(纯虚函数定义接口)
class User {
protected:
string name; // 用户名
ChatRoomMediator* mediator; // 关联的中介者
public:
User(const string& name) : name(name), mediator(nullptr) {
if (name.empty())
throw invalid_argument("用户名不可为空");
}
virtual ~User() = default; // 虚析构函数

// 绑定中介者
void setMediator(ChatRoomMediator* med) { mediator = med; }
// 获取用户名
string getName() const { return name; }
/// <summary>
/// 发送消息(纯虚函数,由子类实现)
/// </summary>
/// <param name="message">消息内容</param>
virtual void sendMessage(const string& message) = 0;
/// <summary>
/// 接收消息(纯虚函数,由子类实现)
/// </summary>
/// <param name="message">消息内容</param>
/// <param name="senderName">发送者用户名</param>
virtual void receiveMessage(const string& message, const string& senderName) = 0;
};

// 具体中介者:在线聊天室
class ConcreteChatRoom : public ChatRoomMediator {
private:
vector<User*> users; // 在线用户列表(存储用户指针)
mutex mtx; // 互斥锁,保证并发安全
public:
~ConcreteChatRoom() override {
// 释放所有用户指针,避免内存泄漏
for (User* user : users) {
delete user;
}
users.clear();
}

void registerUser(User* user) override {
if (user == nullptr)
throw invalid_argument("用户实例不可为nullptr");
lock_guard<mutex> lock(mtx);
// 避免重复注册
for (User* u : users) {
if (u == user)
return;
}
users.push_back(user);
user->setMediator(this); // 绑定中介者
cout << "用户【" << user->getName() << "】加入聊天室" << endl;
}

void sendMessage(const string& message, User* sender) override {
if (sender == nullptr)
throw invalid_argument("发送者实例不可为nullptr");
if (message.empty())
throw invalid_argument("消息内容不可为空");
lock_guard<mutex> lock(mtx);
// 转发消息,发送者不接收自己的消息
for (User* user : users) {
if (user != sender) {
user->receiveMessage(message, sender->getName());
}
}
}
};

// 具体同事类:普通用户
class NormalUser : public User {
public:
NormalUser(const string& name) : User(name) {}

void sendMessage(const string& message) override {
if (mediator == nullptr)
throw runtime_error("用户未加入任何聊天室,无法发送消息");
cout << "\n" << name << " 发送消息:" << message << endl;
mediator->sendMessage(message, this); // 通过中介者转发消息
}

void receiveMessage(const string& message, const string& senderName) override {
cout << name << " 收到 " << senderName << " 的消息:" << message << endl;
}
};

// 客户端测试代码
int main() {
try {
// 1. 初始化中介者(聊天室)
ChatRoomMediator* chatRoom = new ConcreteChatRoom();

// 2. 初始化具体同事类(用户)并注册
User* user1 = new NormalUser("张三");
User* user2 = new NormalUser("李四");
User* user3 = new NormalUser("王五");
chatRoom->registerUser(user1);
chatRoom->registerUser(user2);
chatRoom->registerUser(user3);

// 3. 模拟用户发送消息
user1->sendMessage("大家好!我是张三,很高兴加入聊天室~");
cout << "---" << endl;
user2->sendMessage("张三你好!欢迎加入~");
cout << "---" << endl;
user3->sendMessage("大家好呀!");

// 4. 释放中介者内存(会自动释放所有用户内存)
delete chatRoom;
}
catch (const exception& e) {
cout << "C++ 执行异常:" << e.what() << endl;
}
return 0;
}

2.5 纯C语言实现(结构体+函数指针,模拟面向对象)

纯C语言无面向对象特性,无类和多态,通过“结构体封装数据+函数指针封装行为”,手动模拟中介者模式的核心逻辑。用结构体封装中介者和同事类的属性,用函数指针模拟抽象接口的方法,需手动管理内存,代码虽略显冗余,但底层可控性强,适配嵌入式、底层开发等资源受限场景,完美还原“解耦交互、集中协调”的核心思想。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

// 定义常量,避免魔法数字,提升代码可读性
#define MAX_USER_NAME_LEN 20 // 最大用户名长度
#define MAX_USERS 10 // 最大在线用户数(适配资源受限场景)
#define MAX_MESSAGE_LEN 100 // 最大消息长度

// 前向声明:解决结构体交叉引用问题
typedef struct User User;
typedef struct ChatRoomMediator ChatRoomMediator;

// 抽象中介者:结构体+函数指针模拟接口
typedef struct ChatRoomMediator {
User* users[MAX_USERS]; // 在线用户数组
int user_count; // 已注册用户数量
pthread_mutex_t mutex; // 互斥锁,保证并发安全
// 中介者方法:注册用户、转发消息
void (*register_user)(ChatRoomMediator* mediator, User* user);
void (*send_message)(ChatRoomMediator* mediator, const char* message, User* sender);
} ChatRoomMediator;

// 抽象同事类:结构体+函数指针模拟接口
typedef struct User {
char name[MAX_USER_NAME_LEN]; // 用户名
ChatRoomMediator* mediator; // 关联的中介者
// 用户方法:发送消息、接收消息
void (*send_message)(User* user, const char* message);
void (*receive_message)(User* user, const char* message, const char* sender_name);
} User;

// 具体中介者方法:注册用户
void chat_room_register_user(ChatRoomMediator* mediator, User* user) {
if (mediator == NULL || user == NULL) {
printf("C: 中介者或用户实例无效\n");
return;
}
pthread_mutex_lock(&mediator->mutex);

// 校验用户数量上限和重复注册
if (mediator->user_count >= MAX_USERS) {
printf("C: 聊天室用户数量已达上限,无法注册\n");
pthread_mutex_unlock(&mediator->mutex);
return;
}
for (int i = 0; i < mediator->user_count; i++) {
if (mediator->users[i] == user) {
printf("C: 用户已注册,无需重复操作\n");
pthread_mutex_unlock(&mediator->mutex);
return;
}
}
// 注册用户并绑定中介者
mediator->users[mediator->user_count++] = user;
user->mediator = mediator;
printf("用户【%s】加入聊天室\n", user->name);
pthread_mutex_unlock(&mediator->mutex);
}

// 具体中介者方法:转发消息
void chat_room_send_message(ChatRoomMediator* mediator, const char* message, User* sender) {
if (mediator == NULL || sender == NULL || message == NULL || strlen(message) == 0) {
printf("C: 中介者、发送者或消息内容无效\n");
return;
}
pthread_mutex_lock(&mediator->mutex);

// 转发消息,发送者不接收自己的消息
for (int i = 0; i < mediator->user_count; i++) {
if (mediator->users[i] != sender) {
mediator->users[i]->receive_message(mediator->users[i], message, sender->name);
}
}
pthread_mutex_unlock(&mediator->mutex);
}

// 具体同事类方法:发送消息
void normal_user_send_message(User* user, const char* message) {
if (user == NULL || message == NULL || strlen(message) == 0) {
printf("C: 用户或消息内容无效\n");
return;
}
if (user->mediator == NULL) {
printf("C: 用户【%s】未加入任何聊天室,无法发送消息\n", user->name);
return;
}
// 截取消息,避免内存溢出
char msg[MAX_MESSAGE_LEN];
strncpy(msg, message, MAX_MESSAGE_LEN - 1);
msg[MAX_MESSAGE_LEN - 1] = '\0';

printf("\n%s 发送消息:%s\n", user->name, msg);
user->mediator->send_message(user->mediator, msg, user); // 通过中介者转发
}

// 具体同事类方法:接收消息
void normal_user_receive_message(User* user, const char* message, const char* sender_name) {
if (user == NULL || message == NULL || sender_name == NULL) {
printf("C: 用户、消息或发送者信息无效\n");
return;
}
printf("%s 收到 %s 的消息:%s\n", user->name, sender_name, message);
}

// 工厂函数:创建聊天室(中介者)实例
ChatRoomMediator* create_chat_room() {
ChatRoomMediator* mediator = (ChatRoomMediator*)malloc(sizeof(ChatRoomMediator));
if (mediator == NULL) {
printf("C: 内存分配失败,无法创建聊天室\n");
return NULL;
}
// 初始化用户数组和计数
memset(mediator->users, 0, sizeof(mediator->users));
mediator->user_count = 0;
// 初始化互斥锁
pthread_mutex_init(&mediator->mutex, NULL);
// 绑定中介者方法
mediator->register_user = chat_room_register_user;
mediator->send_message = chat_room_send_message;
return mediator;
}

// 工厂函数:创建普通用户(同事类)实例
User* create_normal_user(const char* name) {
if (name == NULL || strlen(name) == 0 || strlen(name) >= MAX_USER_NAME_LEN) {
printf("C: 用户名无效(为空或长度过长)\n");
return NULL;
}
User* user = (User*)malloc(sizeof(User));
if (user == NULL) {
printf("C: 内存分配失败,无法创建用户\n");
return NULL;
}
// 复制用户名,避免野指针
strncpy(user->name, name, MAX_USER_NAME_LEN - 1);
user->name[MAX_USER_NAME_LEN - 1] = '\0';
user->mediator = NULL;
// 绑定用户方法
user->send_message = normal_user_send_message;
user->receive_message = normal_user_receive_message;
return user;
}

// 释放用户内存
void destroy_user(User* user) {
if (user != NULL) {
free(user);
user = NULL;
}
}

// 释放聊天室内存
void destroy_chat_room(ChatRoomMediator* mediator) {
if (mediator != NULL) {
pthread_mutex_destroy(&mediator->mutex);
free(mediator);
mediator = NULL;
}
}

// 客户端测试代码
int main() {
// 1. 创建中介者(聊天室)
ChatRoomMediator* chat_room = create_chat_room();
if (chat_room == NULL) return -1;

// 2. 创建具体同事类(用户)
User* user1 = create_normal_user("张三");
User* user2 = create_normal_user("李四");
User* user3 = create_normal_user("王五");
if (user1 == NULL || user2 == NULL || user3 == NULL) {
destroy_user(user1);
destroy_user(user2);
destroy_user(user3);
destroy_chat_room(chat_room);
return -1;
}

// 3. 注册用户到聊天室
chat_room->register_user(chat_room, user1);
chat_room->register_user(chat_room, user2);
chat_room->register_user(chat_room, user3);

// 4. 模拟用户发送消息
user1->send_message(user1, "大家好!我是张三,很高兴加入聊天室~");
printf("---\n");
user2->send_message(user2, "张三你好!欢迎加入~");
printf("---\n");
user3->send_message(user3, "大家好呀!");

// 5. 释放内存
destroy_user(user1);
destroy_user(user2);
destroy_user(user3);
destroy_chat_room(chat_room);
return 0;
}

三、中介者模式的优缺点

中介者模式的核心价值是“解耦多对象间的复杂交互,集中管理协调逻辑”,其优缺点均围绕这一核心展开。在实际开发中,需结合业务场景的交互复杂度、对象数量和性能要求,权衡使用,避免过度设计或滥用,确保既发挥其核心优势,又规避潜在问题。

3.1 核心优点

  • 降低系统耦合度,符合迪米特法则:同事类之间不再直接交互,仅通过中介者通信,消除了对象间的网状依赖,将“多对多”耦合转化为“一对多”耦合,大幅提升代码的可维护性和可扩展性,符合“最少知道原则”。

  • 集中管理交互逻辑,简化维护:所有对象间的交互规则都封装在中介者中,无需分散在各个同事类中,修改交互逻辑时仅需修改中介者代码,无需改动同事类,降低维护成本,提升开发效率。

  • 简化同事类设计,聚焦核心业务:同事类无需关注其他同事的实现细节和交互逻辑,只需实现自身的核心业务逻辑,以及与中介者的通信方法,职责单一,代码更简洁、清晰。

  • 提升系统灵活性,便于扩展:新增同事类时,仅需让其实现抽象同事类接口,并注册到中介者中,无需修改原有同事类和中介者的核心逻辑;修改交互规则时,仅需调整中介者的转发逻辑,扩展性极强。

  • 便于调试和问题定位:所有交互都经过中介者转发,可在中介者中统一添加日志、监控等功能,快速定位交互过程中的问题,降低调试难度。

3.2 主要缺点

  • 中介者易成为“上帝类”,复杂度攀升:当系统中同事类数量增多、交互逻辑复杂时,中介者会承担过多的协调职责,导致代码臃肿、逻辑繁琐,难以维护和扩展,违背“单一职责原则”。

  • 存在性能瓶颈风险:所有交互都需经过中介者转发,若中介者处理逻辑复杂(如多条件判断、批量转发),在高频交互场景下,会增加系统响应延迟,成为性能瓶颈。

  • 可能违反开闭原则:若新增的交互规则需要修改中介者的核心逻辑,而非仅扩展中介者,会违反“开闭原则”,增加系统的迭代风险。

  • 中介者依赖过重,容错性降低:中介者是整个交互体系的核心,若中介者出现故障,会导致所有同事类之间的交互中断,系统容错性降低,需额外设计降级、容错机制。

四、中介者模式的使用场景

中介者模式的核心适用场景是“多个对象之间存在频繁、复杂的交互,导致对象间耦合度高、维护困难”的业务场景。以下结合具体场景及典型实战案例,帮助开发者快速判断是否适用,实现精准落地,避免滥用或错用。

4.1 核心适用场景

  • 多组件交互场景:GUI界面中的多组件协同(如窗体中的按钮、输入框、下拉框、弹窗等),通过中介者(窗体控制器)协调组件间的交互,避免组件间直接耦合(如按钮点击后更新输入框内容、隐藏下拉框)。

  • 分布式系统通信场景:微服务架构中,多个微服务之间的通信,通过消息中间件、API网关(中介者)转发请求,避免服务间直接调用,降低服务耦合,提升系统的可扩展性。

  • 多人协作场景:在线聊天室、游戏大厅、协同办公工具等,用户/玩家之间的消息转发、状态同步,通过中介者统一处理,简化多用户间的交互逻辑。

  • 复杂流程协同场景:订单流程、支付流程等,涉及订单、支付、库存、物流、通知等多个模块,通过中介者协调各模块的交互(如支付成功后,通知库存扣减、物流创建、短信推送)。

  • 网络协议交互场景:TCP/IP协议栈中,各层协议(物理层、数据链路层、网络层、传输层)之间的交互,通过中间层(中介者)转发数据,避免各层直接耦合,简化协议实现。

  • 设备联动场景:智能家居系统中,多个设备(灯光、空调、窗帘、传感器)之间的联动,通过网关(中介者)协调设备状态同步和指令转发,避免设备间直接通信。

4.2 典型实战案例

  • 在线聊天室:本文实现的经典案例,多个用户通过聊天室(中介者)发送和接收消息,用户无需直接交互,由聊天室统一转发,简化多用户通信逻辑,降低耦合,同时便于扩展(如新增管理员用户、消息过滤功能)。

  • 电商订单流程:订单创建后,需联动支付、库存、物流、通知等模块,通过订单中介者协调各模块交互:支付模块完成支付后,通知中介者,中介者再分别调用库存扣减、物流创建、短信通知逻辑,各模块无需直接关联,便于单独升级和维护。

  • GUI组件交互:桌面应用的登录窗体,包含用户名输入框、密码输入框、登录按钮、重置按钮、提示框等组件,通过窗体控制器(中介者)协调交互:点击登录按钮时,中介者校验输入框内容,若校验通过则提交登录请求,若失败则通过提示框显示错误信息,组件间无直接依赖。

  • 游戏大厅系统:多人在线游戏中,玩家的加入、退出、聊天、状态同步等操作,通过游戏大厅(中介者)统一处理,玩家无需直接与其他玩家通信,中介者负责转发消息、同步状态,提升系统并发处理能力。

4.3 不适用场景

  • 对象间交互简单、数量少的场景:若仅2-3个对象,且交互逻辑简单,直接通信更简洁,引入中介者会增加系统复杂度,属于过度设计。

  • 高频交互、对性能要求极高的场景:如高频交易系统,中介者的转发逻辑会增加响应延迟,影响系统性能,不建议使用。

  • 交互规则频繁变化的场景:若交互规则频繁迭代,会导致中介者代码频繁修改,违背开闭原则,增加维护成本。

五、总结

中介者模式作为一种核心的行为型设计模式,核心精髓是通过引入中介者对象,将多对象间的网状依赖转化为星型依赖,实现“解耦交互、集中协调”的核心目标。其本质是将分散在多个对象中的交互逻辑,抽取到中介者中统一管理,让同事类聚焦自身核心业务,提升系统的可维护性、可扩展性和可读性。

从多语言实现来看,不同语言的实现方式虽有差异,但核心逻辑高度一致:面向对象语言(C#、Python、Go、C++)可通过接口/抽象类+实现类的方式,自然映射中介者模式的四大核心角色,依托多态、继承等特性简化代码;纯C语言则通过结构体+函数指针模拟面向对象特性,手动实现核心逻辑,虽代码冗余,但底层可控,适配资源受限场景。各语言的实现均需关注边界处理、异常捕获和并发安全,确保代码可运行、高可靠。

在工程实践中,使用中介者模式的关键的是“平衡”:既要发挥其解耦、集中管理的优势,也要规避中介者成为“上帝类”的风险。实践中可通过以下方式优化:一是拆分细粒度中介者,将复杂交互逻辑拆分到多个中介者中,遵循单一职责原则;二是结合其他设计模式,如工厂模式创建中介者和同事类、观察者模式优化中介者与同事类的通信,提升系统灵活性;三是针对高频交互场景,优化中介者转发逻辑,减少性能损耗;四是为中介者设计容错机制,避免核心节点故障导致整个系统瘫痪。

总之,中介者模式是解决多对象复杂交互问题的有效工具,并非所有场景都适用,需结合业务实际权衡取舍。合理使用可使系统结构更清晰、扩展更灵活,滥用则会增加系统复杂度和维护成本。开发者在实际开发中,应先分析对象间的交互复杂度,再决定是否引入中介者模式,确保设计既符合设计原则,又贴合工程实践需求。