行为型模式:⑤中介者模式(Mediator Pattern)
核心思想
定义一个中介者对象,封装多个对象(同事类)之间的交互逻辑,使同事类之间无需直接通信,仅通过中介者传递消息,从而降低同事类的耦合度,集中管理交互规则,便于维护和扩展。
核心本质
交互集中化,将 “网状交织的同事交互” 转化为 “星状的中介者 - 同事交互”,解决多对象依赖导致的耦合爆炸问题。
典型场景
团队协作系统(如项目组内成员通过项目经理传递信息);
聊天软件(用户通过服务器转发消息,无需直接连接);
界面组件交互(如按钮点击后,通过中介者更新输入框、列表框等多个组件);
分布式系统中的协调器(如微服务注册中心、配置中心)。
C 语言实现(结构体 + 函数指针 + 集中交互)
C 语言无类,通过 “结构体模拟角色”“函数指针定义接口”“中介者持有同事列表”,实现同事间的间接通信。核心是:中介者维护所有同事的引用,同事发送消息时委托中介者转发,中介者负责调用目标同事的接收逻辑。
场景示例
办公室消息通知系统:
抽象中介者(Mediator):定义 “注册同事”“转发消息” 接口;
具体中介者(AdminMediator):行政部,维护员工列表,转发消息给所有 / 指定员工;
同事类(Colleague):员工,持有中介者指针,支持 “发送消息”“接收消息”;
具体同事类(Employee):实际员工,通过行政部发送消息,接收行政部转发的消息。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 最大同事数量
#define MAX_COLLEAGUES 10
// 最大消息长度
#define MAX_MSG_LEN 128
// 最大用户名长度
#define MAX_NAME_LEN 32
// 前置声明:同事结构体(供中介者使用)
typedef struct Colleague Colleague;
// -------------------------- 1. 抽象中介者(Mediator):统一交互接口 --------------------------
typedef struct Mediator {
// 注册同事(将同事加入中介者管理列表)
void (*register_colleague)(struct Mediator* self, Colleague* colleague);
// 转发消息(同事发送的消息通过中介者转发)
void (*forward_message)(struct Mediator* self, const Colleague* sender, const char* msg);
// 销毁中介者
void (*destroy)(struct Mediator* self);
// 管理的同事列表
Colleague* colleagues[MAX_COLLEAGUES];
int colleague_count; // 已注册同事数量
} Mediator;
// -------------------------- 2. 同事类(Colleague):与中介者交互的对象 --------------------------
struct Colleague {
char name[MAX_NAME_LEN]; // 同事名称(如员工姓名)
Mediator* mediator; // 持有中介者指针(关键:通过中介者通信)
// 发送消息(委托中介者转发)
void (*send_msg)(struct Colleague* self, const char* msg);
// 接收消息(中介者调用此方法传递消息)
void (*recv_msg)(struct Colleague* self, const char* sender, const char* msg);
// 销毁同事
void (*destroy)(struct Colleague* self);
};
// -------------------------- 3. 具体中介者(AdminMediator):行政部(实现转发逻辑) --------------------------
typedef struct AdminMediator {
Mediator base; // 继承抽象中介者接口
} AdminMediator;
// 具体中介者:注册同事
void admin_register_colleague(Mediator* self, Colleague* colleague) {
if (self->colleague_count >= MAX_COLLEAGUES) {
printf("[行政部] 同事数量已达上限,无法注册新同事!\n");
return;
}
self->colleagues[self->colleague_count++] = colleague;
printf("[行政部] 员工「%s」已注册到消息系统\n", colleague->name);
}
// 具体中介者:转发消息(发给所有其他同事)
void admin_forward_message(Mediator* self, const Colleague* sender, const char* msg) {
printf("\n[行政部] 收到「%s」的消息:%s → 开始转发给所有员工...\n", sender->name, msg);
// 遍历所有同事,排除发送者,调用接收消息方法
for (int i = 0; i < self->colleague_count; i++) {
Colleague* receiver = self->colleagues[i];
if (receiver != sender) { // 不转发给发送者自己
receiver->recv_msg(receiver, sender->name, msg);
}
}
}
// 具体中介者:销毁(无需额外释放,同事由客户端单独销毁)
void admin_destroy(Mediator* self) {
free(self);
printf("\n[行政部] 消息系统已关闭\n");
}
// 创建具体中介者(行政部)
Mediator* create_admin_mediator() {
AdminMediator* admin = (AdminMediator*)malloc(sizeof(AdminMediator));
admin->base.register_colleague = admin_register_colleague;
admin->base.forward_message = admin_forward_message;
admin->base.destroy = admin_destroy;
admin->base.colleague_count = 0;
memset(admin->base.colleagues, 0, sizeof(admin->base.colleagues));
return (Mediator*)admin;
}
// -------------------------- 4. 具体同事类(Employee):员工(实现发送/接收逻辑) --------------------------
typedef struct Employee {
Colleague base; // 继承同事接口
} Employee;
// 具体同事:发送消息(委托中介者转发)
void employee_send_msg(Colleague* self, const char* msg) {
if (self->mediator == NULL) {
printf("[%s] 未注册到消息系统,无法发送消息!\n", self->name);
return;
}
printf("[%s] 发送消息:%s\n", self->name, msg);
self->mediator->forward_message(self->mediator, self, msg);
}
// 具体同事:接收消息
void employee_recv_msg(Colleague* self, const char* sender, const char* msg) {
printf("[%s] 收到「%s」的消息:%s\n", self->name, sender, msg);
}
// 具体同事:销毁
void employee_destroy(Colleague* self) {
free(self);
printf("[%s] 已退出消息系统\n", self->name);
}
// 创建具体同事(员工)
Colleague* create_employee(const char* name, Mediator* mediator) {
Employee* emp = (Employee*)malloc(sizeof(Employee));
strncpy(emp->base.name, name, MAX_NAME_LEN);
emp->base.mediator = mediator; // 绑定中介者
emp->base.send_msg = employee_send_msg;
emp->base.recv_msg = employee_recv_msg;
emp->base.destroy = employee_destroy;
return (Colleague*)emp;
}
// -------------------------- 测试代码(客户端) --------------------------
int main() {
// 1. 创建中介者(行政部)
Mediator* admin = create_admin_mediator();
// 2. 创建同事(员工)并注册到中介者
Colleague* zhangsan = create_employee("张三", admin);
Colleague* lisi = create_employee("李四", admin);
Colleague* wangwu = create_employee("王五", admin);
admin->register_colleague(admin, zhangsan);
admin->register_colleague(admin, lisi);
admin->register_colleague(admin, wangwu);
// 3. 同事发送消息(通过中介者转发)
zhangsan->send_msg(zhangsan, "明天上午10点开项目例会,请大家准时参加!");
lisi->send_msg(lisi, "会议资料已上传到共享盘,链接:xxx");
wangwu->send_msg(wangwu, "收到,准时参会~");
// 4. 销毁资源
printf("\n=== 退出消息系统 ===");
zhangsan->destroy(zhangsan);
lisi->destroy(lisi);
wangwu->destroy(wangwu);
admin->destroy(admin);
return 0;
}
实现关键要点
1.中介者持有同事列表:具体中介者(AdminMediator)通过数组维护所有注册的同事,确保能遍历转发消息,是 “集中交互” 的核心。
2.同事依赖中介者:每个同事(Employee)持有中介者指针,发送消息时不直接调用其他同事,而是委托中介者的 forward_message 方法,彻底解耦同事间的直接依赖。
3.接口统一:抽象中介者(Mediator)和同事(Colleague)通过函数指针定义统一接口,具体实现类(AdminMediator/Employee)绑定对应逻辑,客户端无需区分具体类型。
4.交互逻辑集中:所有同事间的通信规则(如 “转发给所有其他同事”)都集中在中介者中,修改交互规则时仅需修改中介者,无需修改同事代码,符合 “单一职责原则”。
5.扩展性:新增同事(如 “赵六”)时,仅需创建 Employee 并注册到中介者;新增交互规则(如 “转发给指定部门员工”)时,仅需修改中介者的 forward_message 方法,符合 “开闭原则”。
6.内存管理:同事和中介者需手动销毁,中介者不负责同事的生命周期(客户端单独管理),避免循环引用导致的内存泄漏。
C++ 实现(类 + 继承 + 多态 + 集中管理)
通过 “抽象基类 + 继承” 定义中介者和同事接口,利用多态实现灵活交互,STL 容器简化同事管理,智能指针自动维护内存,代码更简洁、类型更安全。
场景示例
同 C 语言:办公室消息通知系统,抽象中介者 Mediator、具体中介者 AdminMediator、抽象同事 Colleague、具体同事 Employee,同事通过中介者转发消息。
#include <iostream>
#include <string>
#include <vector>
#include <memory> // 智能指针(自动管理内存)
using namespace std;
// 前置声明:同事类(供中介者使用)
class Colleague;
// -------------------------- 1. 抽象中介者(Mediator):抽象基类 --------------------------
class Mediator {
public:
virtual ~Mediator() = default; // 虚析构:确保子类析构被调用
// 纯虚函数:注册同事
virtual void registerColleague(shared_ptr<Colleague> colleague) = 0;
// 纯虚函数:转发消息
virtual void forwardMessage(const Colleague* sender, const string& msg) = 0;
};
// -------------------------- 2. 抽象同事(Colleague):抽象基类 --------------------------
class Colleague {
public:
Colleague(string name, shared_ptr<Mediator> mediator)
: name_(move(name)), mediator_(move(mediator)) {}
virtual ~Colleague() = default;
// 纯虚函数:发送消息
virtual void sendMsg(const string& msg) = 0;
// 纯虚函数:接收消息
virtual void recvMsg(const string& sender, const string& msg) = 0;
// 获取同事名称(供中介者使用)
string getName() const { return name_; }
protected:
string name_; // 同事名称
shared_ptr<Mediator> mediator_;// 持有中介者智能指针(解耦+自动内存管理)
};
// -------------------------- 3. 具体中介者(AdminMediator):行政部 --------------------------
class AdminMediator : public Mediator {
public:
void registerColleague(shared_ptr<Colleague> colleague) override {
// 用vector存储同事智能指针,自动管理同事生命周期
colleagues_.push_back(colleague);
cout << "[行政部] 员工「" << colleague->getName() << "」已注册到消息系统" << endl;
}
void forwardMessage(const Colleague* sender, const string& msg) override {
cout << "\n[行政部] 收到「" << sender->getName() << "」的消息:" << msg
<< " → 开始转发给所有员工..." << endl;
// 遍历所有同事,转发消息(排除发送者)
for (const auto& colleague : colleagues_) {
if (colleague.get() != sender) { // 避免给自己发消息
colleague->recvMsg(sender->getName(), msg);
}
}
}
private:
// 存储同事智能指针,避免野指针,自动释放
vector<shared_ptr<Colleague>> colleagues_;
};
// -------------------------- 4. 具体同事(Employee):员工 --------------------------
class Employee : public Colleague {
public:
Employee(string name, shared_ptr<Mediator> mediator)
: Colleague(move(name), move(mediator)) {}
void sendMsg(const string& msg) override {
if (!mediator_) {
cout << "[" << name_ << "] 未注册到消息系统,无法发送消息!" << endl;
return;
}
cout << "[" << name_ << "] 发送消息:" << msg << endl;
// 委托中介者转发消息
mediator_->forwardMessage(this, msg);
}
void recvMsg(const string& sender, const string& msg) override {
cout << "[" << name_ << "] 收到「" << sender << "」的消息:" << msg << endl;
}
};
// -------------------------- 测试代码(客户端) --------------------------
int main() {
// 1. 创建中介者(智能指针自动管理内存)
auto admin = make_shared<AdminMediator>();
// 2. 创建同事(员工)并注册到中介者
auto zhangsan = make_shared<Employee>("张三", admin);
auto lisi = make_shared<Employee>("李四", admin);
auto wangwu = make_shared<Employee>("王五", admin);
admin->registerColleague(zhangsan);
admin->registerColleague(lisi);
admin->registerColleague(wangwu);
// 3. 同事发送消息
zhangsan->sendMsg("明天上午10点开项目例会,请大家准时参加!");
lisi->sendMsg("会议资料已上传到共享盘,链接:xxx");
wangwu->sendMsg("收到,准时参会~");
return 0; // 智能指针自动销毁所有对象,无需手动释放
}
实现关键要点
1.抽象基类定义接口:Mediator 和 Colleague 为抽象基类,纯虚函数定义统一交互接口(registerColleague/forwardMessage、sendMsg/recvMsg),具体类继承并实现,确保多态调用。
2.智能指针管理内存:中介者和同事均用 shared_ptr 管理,自动处理生命周期,避免野指针和内存泄漏;虚析构函数确保子类析构被正确调用。
3.解耦彻底:同事仅依赖 Mediator 抽象基类,不依赖具体中介者或其他同事;中介者仅依赖 Colleague 抽象基类,不依赖具体同事,符合 “依赖倒置原则”。
4.STL 容器简化管理:中介者用 vector 存储同事智能指针,无需手动维护数组索引和容量,遍历转发更简洁。
5.交互逻辑集中:所有同事间的通信规则集中在 AdminMediator 的 forwardMessage 方法中,修改规则(如按部门转发、私信功能)仅需修改中介者,无需改动同事代码。
6.扩展性强:新增同事(如 “赵六”)仅需创建 Employee 实例并注册;新增中介者(如 “技术部中介者”)仅需继承 Mediator 并实现接口,客户端代码无需修改,符合 “开闭原则”。
7.类型安全:C++ 的编译期类型检查和多态机制,避免 C 语言中函数指针绑定错误或类型转换风险,代码更可靠。
中介者模式核心总结(C vs C++)

设计原则
单一职责原则:中介者管交互,同事管自身业务,各司其职;
开闭原则:新增同事或交互规则,无需修改现有代码;
依赖倒置原则:同事和中介者均依赖抽象,不依赖具体实现;
迪米特法则(最少知识原则):同事仅与中介者通信,不与其他同事直接交互,减少依赖。
1198

被折叠的 条评论
为什么被折叠?



