中介者模式是一种行为型设计模式,其核心思想是通过一个 “中介者” 对象,封装多个对象(称为 “同事对象”)之间的交互关系,使同事对象无需直接相互引用,仅通过中介者传递信息,从而降低对象间的耦合度,简化系统结构。

该模式的本质是 “集中控制交互” —— 将原本分散在多个同事对象之间的复杂交互逻辑,转移到中介者中统一管理,让同事对象专注于自身的核心功能,而非与其他对象的通信细节。

中介者模式的UML如下:

image.png

中介者模式的典型应用场景如下:

  1. 对象间存在复杂交互
    • 聊天室 / 群聊系统:用户(同事)发送消息时,无需直接发给每个成员,通过聊天室(中介者)统一转发;
    • 图形界面(GUI)组件交互:如 “按钮点击后触发文本框清空、列表刷新”,通过窗口(中介者)协调按钮、文本框、列表的交互。
  2. 系统存在 “多对多” 依赖
    • 订单处理系统:订单(同事)、库存(同事)、支付(同事)、物流(同事)的交互,通过 “订单中介者” 协调(如支付成功后,中介者通知库存扣减、物流创建);
    • 智能家居系统:灯光(同事)、空调(同事)、窗帘(同事)通过 “中控系统(中介者)” 联动(如 “离家模式” 触发所有设备关闭)。
  3. 需要集中控制交互规则
    • 游戏中的 “战斗管理器”:玩家(同事)、怪物(同事)、道具(同事)的交互,通过战斗管理器(中介者)计算伤害、判定胜负。

下面我将用 Java 代码实现中介者模式,以聊天室系统为例,展示中介者如何协调多个用户之间的交互。

首先,我们定义一个抽象的中介者对象Mediator,它定义了注册同事和转发消息的接口,是中介者和同事之间交互的契约。

1
2
3
4
5
6
7
8
9
// 抽象中介者接口
public abstract class Mediator {
// 注册同事对象
public abstract void register(Colleague colleague);

// 转发消息
public abstract void relay(Colleague colleague, String message);
}

在我们的例子中聊天室是一个具体的中介者,它实现了聊天室的功能,维护着所有用户的列表并负责将消息转发给其他所有用户。

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
import java.util.ArrayList;
import java.util.List;

// 具体中介者:聊天室
public class ChatRoomMediator extends Mediator {
// 维护所有注册的用户
private List<Colleague> colleagues = new ArrayList<>();

@Override
public void register(Colleague colleague) {
// 如果用户未注册,则添加到列表
if (!colleagues.contains(colleague)) {
colleagues.add(colleague);
}
}

@Override
public void relay(Colleague colleague, String message) {
// 向除发送者外的所有用户转发消息
for (Colleague c : colleagues) {
if (!c.equals(colleague)) {
c.receive(colleague.getName(), message);
}
}
}
}

我们这个例子中,消息是在不同的用户(同事)之间转发的,因此我们定义一个抽象的同事类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 抽象同事类:用户
public abstract class Colleague {
protected Mediator mediator;
protected String name;

// 构造方法,传入中介者和用户名
public Colleague(Mediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}

// 发送消息
public abstract void send(String message);

// 接收消息
public abstract void receive(String senderName, String message);

// 获取用户名
public String getName() {
return name;
}
}

在上面这个类中,定义了用户的基本行为,包括发送和接收消息,并持有一个中介者的引用。

在具体的用户类中,我们实现具体行为,发送消息时通过中介者转发,接收消息时显示接收到的内容。这里重要的一点是消息似乎通过中介者转发的而不是用户直接发送。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 具体同事类:用户实现
public class User extends Colleague {

public User(Mediator mediator, String name) {
super(mediator, name);
}

@Override
public void send(String message) {
System.out.println(name + "发送消息: " + message);
// 通过中介者转发消息
mediator.relay(this, message);
}

@Override
public void receive(String senderName, String message) {
System.out.println(name + "收到来自" + senderName + "的消息: " + message);
}
}

最后我们通过客户端代码来演示这个模式的使用:

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
// 客户端测试
public class Client {
public static void main(String[] args) {
// 创建中介者:聊天室
Mediator chatRoom = new ChatRoomMediator();

// 创建同事:用户
Colleague user1 = new User(chatRoom, "张三");
Colleague user2 = new User(chatRoom, "李四");
Colleague user3 = new User(chatRoom, "王五");

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

// 发送消息测试
user1.send("大家好,我是张三!");
System.out.println("-----");
user2.send("欢迎张三加入聊天室!");
System.out.println("-----");
user3.send("你们好啊!");
}
}

我们可以看到:

  1. 客户端创建中介者实例(聊天室)
  2. 创建同事对象(用户),并在构造时传入中介者引用
  3. 将所有同事注册到中介者中
  4. 当一个同事发送消息时:
    • 调用自身的 send () 方法
    • send () 方法通过中介者的 relay () 方法转发消息
    • 中介者将消息分发给其他所有同事
    • 其他同事通过 receive () 方法处理消息

这种设计使得用户之间无需直接相互引用,所有交互都通过中介者完成,降低了系统的耦合度,便于后续扩展新的功能。