第一部分:模式基础详解
1. 模式概述
中介者模式(Mediator Pattern)是一种行为设计模式,通过引入一个中介对象来封装一组对象之间的交互。中介者使各对象不需要显式地相互引用,从而降低耦合度,并可以独立地改变它们之间的交互。
2. 核心角色
3. 应用场景
- 聊天室系统:用户通过聊天室发送和接收消息
- 航空管制系统:塔台协调飞机起降
- GUI组件交互:按钮、文本框、下拉框等组件的联动
- 表单验证:多个表单字段的相互依赖验证
- 工作流引擎:协调多个任务节点
4. C++代码示例
场景:智能家居控制系统
#include <iostream>
#include <string>
#include <memory>
#include <vector>
// 前向声明
class Colleague;
// 中介者接口
class Mediator {
public:
virtual ~Mediator() = default;
virtual void notify(const std::string& sender, const std::string& event) = 0;
};
// 抽象同事类
class Colleague {
protected:
std::shared_ptr<Mediator> mediator;
std::string name;
public:
Colleague(const std::string& n) : name(n) {}
void setMediator(std::shared_ptr<Mediator> m) {
mediator = m;
}
virtual void send(const std::string& event) {
if (mediator) {
mediator->notify(name, event);
}
}
virtual void receive(const std::string& event) = 0;
std::string getName() const { return name; }
virtual ~Colleague() = default;
};
// 具体同事类:灯
class Light : public Colleague {
private:
bool isOn = false;
public:
Light(const std::string& n) : Colleague(n) {}
void receive(const std::string& event) override {
if (event == "turn_on") {
isOn = true;
std::cout << name << " 已打开" << std::endl;
} else if (event == "turn_off") {
isOn = false;
std::cout << name << " 已关闭" << std::endl;
}
}
bool getStatus() const { return isOn; }
};
// 具体同事类:空调
class AirConditioner : public Colleague {
private:
int temperature = 22;
public:
AirConditioner(const std::string& n) : Colleague(n) {}
void receive(const std::string& event) override {
if (event == "turn_on") {
std::cout << name << " 已打开,当前温度:" << temperature << "°C" << std::endl;
} else if (event == "turn_off") {
std::cout << name << " 已关闭" << std::endl;
} else if (event.substr(0, 12) == "set_temp_to_") {
temperature = std::stoi(event.substr(12));
std::cout << name << " 温度设置为:" << temperature << "°C" << std::endl;
}
}
};
// 具体同事类:智能音箱
class SmartSpeaker : public Colleague {
public:
SmartSpeaker(const std::string& n) : Colleague(n) {}
void receive(const std::string& event) override {
if (event == "play_music") {
std::cout << name << " 开始播放音乐" << std::endl;
} else if (event == "stop_music") {
std::cout << name << " 停止播放音乐" << std::endl;
} else if (event == "weather_report") {
std::cout << name << " 播报天气:晴天,25°C" << std::endl;
}
}
};
// 具体中介者:智能家居控制中心
class SmartHomeHub : public Mediator, public std::enable_shared_from_this<SmartHomeHub> {
private:
std::vector<std::shared_ptr<Colleague>> devices;
public:
void addDevice(std::shared_ptr<Colleague> device) {
devices.push_back(device);
device->setMediator(shared_from_this());
}
void notify(const std::string& sender, const std::string& event) override {
std::cout << "\n[智能家居中心] 收到来自 " << sender << " 的事件: " << event << std::endl;
if (event == "good_morning") {
// 早安模式:开灯、设置空调温度、播放新闻
for (auto& device : devices) {
if (device->getName() == "客厅灯") {
device->receive("turn_on");
} else if (device->getName() == "空调") {
device->receive("turn_on");
device->receive("set_temp_to_24");
} else if (device->getName() == "智能音箱") {
device->receive("weather_report");
}
}
}
else if (event == "good_night") {
// 晚安模式:关灯、关空调、停止音乐
for (auto& device : devices) {
if (device->getName() == "客厅灯" || device->getName() == "卧室灯") {
device->receive("turn_off");
} else if (device->getName() == "空调") {
device->receive("turn_off");
} else if (device->getName() == "智能音箱") {
device->receive("stop_music");
}
}
}
else if (event == "leave_home") {
// 离家模式:关闭所有设备
for (auto& device : devices) {
device->receive("turn_off");
}
}
else if (event == "light_on") {
// 特定设备控制
for (auto& device : devices) {
if (device->getName() == "客厅灯") {
device->receive("turn_on");
}
}
}
}
};
// 客户端代码
int main() {
// 创建中介者
auto hub = std::make_shared<SmartHomeHub>();
// 创建设备
auto livingLight = std::make_shared<Light>("客厅灯");
auto bedroomLight = std::make_shared<Light>("卧室灯");
auto ac = std::make_shared<AirConditioner>("空调");
auto speaker = std::make_shared<SmartSpeaker>("智能音箱");
// 注册设备到中介者
hub->addDevice(livingLight);
hub->addDevice(bedroomLight);
hub->addDevice(ac);
hub->addDevice(speaker);
// 设备通过中介者通信
std::cout << "=== 早安模式 ===" << std::endl;
speaker->send("good_morning");
std::cout << "\n=== 离家模式 ===" << std::endl;
speaker->send("leave_home");
std::cout << "\n=== 单独控制灯光 ===" << std::endl;
livingLight->send("light_on");
return 0;
}
5. 交互流程图
6. 优缺点分析
优点:
- ✅ 降低对象间耦合,提高可维护性
- ✅ 集中控制交互逻辑,便于修改
- ✅ 符合迪米特法则(最少知识原则)
- ✅ 提高组件复用性
缺点:
- ❌ 中介者可能变得庞大复杂(上帝对象)
- ❌ 增加系统复杂度(需要额外的中介者对象)
- ❌ 调试困难(交互集中在中介者)
7. 与其他模式对比
| 模式 | 适用场景 | 复杂度 |
|---|---|---|
| 中介者 | 多对象网状交互 | 中 |
| 观察者 | 一对多依赖通知 | 低 |
| 外观 | 简化复杂子系统接口 | 低 |
第二部分:核心思想思维深度讲解
1. 思维的本质转变
中介者模式最核心的思维转变是:从“对象知道对象”到“对象只知中介”
2. 四个关键思维转变
思维一:从“知道太多”到“只知必要”
// ❌ 坏味道:对象知道太多其他对象
class BadLight {
AirConditioner* ac;
Speaker* speaker;
Curtain* curtain;
void morningMode() {
ac->turnOn(24);
speaker->play("news");
curtain->open();
this->turnOn();
}
};
// ✅ 中介者思维:只知道中介者
class GoodLight {
Mediator* mediator; // 只需要知道这一个
void morningMode() {
mediator->notify("light", "morning_mode");
}
};
思维二:从“我控制别人”到“我只通知变化”
// ❌ 命令式思维:主动控制别人
class BadUserInterface {
TextBox* nameBox;
TextBox* emailBox;
Button* submitBtn;
void onNameChanged() {
if(nameBox->getText().length() > 0) {
emailBox->enable();
}
if(nameBox->getText().length() > 0 &&
emailBox->getText().contains("@")) {
submitBtn->enable();
}
}
};
// ✅ 声明式思维:只通知状态变化
class GoodUserInterface {
Mediator* mediator;
void onNameChanged() {
mediator->notify("nameBox", "text_changed");
}
};
思维三:从“硬编码路径”到“可配置策略”
思维四:从“点对点通信”到“事件驱动协作”
// 事件驱动的协作思维
class EventDrivenMediator : public Mediator {
map<string, vector<function<void()>>> eventHandlers;
public:
void registerHandler(string event, function<void()> handler) {
eventHandlers[event].push_back(handler);
}
void notify(string sender, string event) override {
// 事件驱动的协作:谁关心谁响应
for(auto& handler : eventHandlers[event]) {
handler(); // 多对多的协作,但彼此不知道
}
}
};
3. 深层哲学思想
3.1 解耦的极致:依赖倒置的应用
// 依赖倒置:都依赖抽象的中介者
class Colleague {
Mediator* mediator; // 依赖抽象,不依赖具体
};
// 具体交互策略可以自由变化
class FlexibleMediator : public Mediator {
// 交互逻辑完全可配置,不影响同事类
map<pair<string, string>, vector<string>> rules;
};
3.2 控制反转的体现
3.3 关注点分离
// 交互逻辑与业务逻辑分离
class BusinessLogic { // 只关心自己的业务
void doWork() { /* 业务逻辑 */ }
};
class InteractionLogic { // 中介者关心交互
void coordinate() {
// 协调多个 BusinessLogic 对象
}
};
4. 高级思维模式
模式一:中介者作为协议
// 将交互协议封装在中介者中
class ProtocolMediator {
// 就像网络协议一样,定义交互规则
enum ProtocolState {
HANDSHAKE,
DATA_TRANSFER,
TERMINATION
};
ProtocolState state;
void handleMessage(Message msg) {
switch(state) {
case HANDSHAKE: /* 握手逻辑 */
case DATA_TRANSFER: /* 数据传输 */
case TERMINATION: /* 终止逻辑 */
}
}
};
模式二:中介者作为路由器
// 智能路由中介者
class RouterMediator {
map<string, string> routingTable; // 消息路由表
void route(string from, string message) {
string to = routingTable[message];
// 根据消息内容智能路由到目标对象
}
};
5. 思维的延伸应用
这个思维模式不仅适用于编程,也适用于:
- 组织管理:部门经理作为中介者协调员工
- 交通系统:交通灯作为中介者协调车辆
- 金融交易:交易所作为中介者匹配买卖订单
6. 思维检查清单
使用中介者模式时,问自己:
- 对象是否知道太多其他对象的细节?
- 修改一个对象是否需要修改多个其他对象?
- 对象的交互逻辑是否难以理解和维护?
- 是否可以在不修改对象本身的情况下改变交互方式?
- 是否可以将交互逻辑提取出来独立变化?
7. 思维陷阱提醒
⚠️ 不要把中介者变成“上帝对象”
// 坏味道:什么都知道的中介者
class GodMediator {
Light* light;
AC* ac;
TV* tv;
Speaker* speaker;
Curtain* curtain;
// ... 100+ 个成员变量
void doEverything() {
// 包含所有业务逻辑
}
};
✅ 正确思维:应该拆分为多个专门的中介者
// 好味道:职责单一的中介者
class LightingMediator { /* 只管理灯光 */ };
class ClimateMediator { /* 只管理温控 */ };
class EntertainmentMediator { /* 只管理娱乐 */ };
第三部分:总结与最佳实践
核心总结
中介者模式的本质思维:
- 减少认知负担:每个对象只需要认识中介者
- 改变控制流向:从对象间相互控制到中介者集中控制
- 提取变化点:将易变的交互逻辑封装在中介者中
- 面向接口协作:所有交互都通过抽象中介者接口
核心价值: 通过增加一个间接层,将网状复杂度转换为星型简洁度,从而让系统更容易理解、维护和扩展。
最佳实践建议
- 适用判断:当系统中存在多对多的复杂交互关系时考虑使用
- 避免上帝对象:将复杂的中介者拆分为多个专门的中介者
- 结合工厂模式:使用工厂创建同事对象,降低耦合
- 异步处理:对于耗时操作,考虑使用异步消息队列
- 命名规范:中介者命名应体现其协调职责(如
XxxCoordinator、XxxHub)
这个模式在实际开发中非常实用,特别是处理复杂UI组件交互、工作流引擎、智能家居控制等场景。
917

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



