目录
一.专栏介绍
本专栏是我学习《head first》设计模式的笔记。这本书中是用Java语言为基础的,我将用C++语言重写一遍,并且详细讲述其中的设计模式,涉及是什么,为什么,怎么做,自己的心得等等。希望阅读者在读完我的这个专题后,也能在开发中灵活且正确的使用,或者在面对面试官时,能够自信地说自己熟悉常用设计模式。
本章将开始**中介者模式(Mediator Pattern)**的学习。
二.中介者模式概念
使用中介者模式来集中相关对象之间复杂的沟通和控制方式。
用一个中介者对象封装一系列对象之间的交互逻辑,让原本相互依赖、直接通信的对象解耦,所有对象只和中介者通信,不再直接引用彼此。
当多个对象之间存在复杂的网状依赖关系 时(比如 A 调用 B、B 调用 C、C 调用 A),代码会变得难以维护、修改和扩展。中介者模式把网状结构 变成星型结构 :所有对象只对接中介者,中介者统一调度交互。中介者就是那颗星星。
网状图:

星状图:

核心角色:
-
抽象中介者(Mediator):定义统一的交互接口,声明对象之间通信的方法;
-
具体中介者(ConcreteMediator):实现抽象中介者,持有所有交互对象的引用,处理具体的交互逻辑;
-
抽象同事类(Colleague):定义公共方法,持有中介者的引用;
-
具体同事类(ConcreteColleague):实现自身业务逻辑,需要交互时,通过中介者通知其他对象。
三.案例与代码
我们实现一个多人聊天室的demo,当聊天室里的用户发送消息时,其他人都会收到。这里的用户就是中介者模式的同事类对象,他们通过中介者类将消息发送给其他人。
代码如下:
mediatorPattern.h:
cpp
#pragma once
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class User;
// 中介者抽象类
class Mediator
{
public:
virtual ~Mediator() = default;
// 依靠User引用将消息发送给User
virtual void send(const string& message, User* sender) = 0;
// 添加User引用
virtual void addUser(User* nUser) = 0;
};
class User
{
public:
User(Mediator* m, string n):
mediator(m), name(n)
{}
virtual ~User() = default;
// 向其他人发送消息,用中介者引用来发送
virtual void send(const string& message) = 0;
// 提供给中介者使用,中介者用这个函数将消息发送给自己
virtual void receive(const string& message) = 0;
protected:
Mediator* mediator; // 中介者引用
string name; // 用户姓名
};
// 中介者具体类
class ConcreteMediator : public Mediator
{
public:
void send(const string& message, User* sender) override
{
for (const auto& user : users)
{
// 不发送给自己(不回显)
if (user != sender) user->receive(message);
}
}
void addUser(User* nUser)
{
users.push_back(nUser);
}
private:
vector<User*> users; // 子类自定义数据结构和提供添加等方法,更灵活
};
class ConcreteUser : public User
{
public:
ConcreteUser(Mediator* m, string n):
User(m, n)
{}
virtual ~ConcreteUser() = default;
void send(const string& message) override
{
mediator->send(message, this);
}
void receive(const string& message)
{
cout << name << "收到消息:" << message << endl;
}
};
代码说明:
- 这里的用户类是中介者模式概念里的同事类。
- 用户类和中介者类持有彼此的引用。
- 中介者类管理用户的数据结构(比如这里的vector)交由具体中介者类定义并实现addUser()虚函数,这样更灵活。
- 用户类send()方法调用中介者引用的send()方法,仅与中介者"这颗星星"交互,中介者再调用各个用户类的引用的receive()方法让他们接收。
main.cpp:
cpp
#include "mediatorPattern.h"
int main()
{
Mediator* mediator = new ConcreteMediator();
User* Bob = new ConcreteUser(mediator, "Bob");
User* Mike = new ConcreteUser(mediator, "Mike");
User* John = new ConcreteUser(mediator, "John");
mediator->addUser(Bob);
mediator->addUser(Mike);
mediator->addUser(John);
Bob->send("Hello everyone!");
cout << endl;
Mike->send("How do you guys think?");
cout << endl;
John->send("Good morning!");
delete mediator;
delete Bob;
delete Mike;
delete John;
return 0;
}
运行输出:

每个用户发送的消息都被其他用户收到了!
四.中介者模式的优点
-
通过将中介者支持的对象从系统解耦,增加了对象的复用性。附和单一职责原则。
-
通过将控制逻辑集中,简化了系统的维护。集中管理交互规则,修改逻辑只需修改中介者 。附和开闭原则。
五.中介者模式的缺点
- 中介者模式的一个缺点是,如果设计不当,中介者对象本身会变得过度复杂。
六.中介者模式的用途
- 多个对象之间存在复杂的相互调用(如GUI组件、聊天室、调度系统)。
- 想要简化对象之间的依赖关系,提高代码可维护性。
- 需要集中控制一组对象的交互行为。
七.中介者模式 vs 观察者模式
观察者模式 == 老师上课
老师(主题)一说话,所有学生(观察者)都听到。一对多、自动广播、不需要中间转发。
中介者模式 == 聊天室
所有人(用户)不直接对话,都发给聊天室(中介者),中介者转发。多对多、互相不认识、完全靠中介调度。
八.总结
-
中介者模式核心:解耦网状依赖,转为星型交互,统一调度;
-
核心角色:抽象中介者、具体中介者、抽象同事、具体同事;
-
核心逻辑:对象不直接通信,全部通过中介者转发 / 调度。