中介者模式:聊天室里的“和事佬”
说实话,中介者模式是我在项目中用得最频繁的模式之一。为什么?因为只要系统里对象一多,通信就会乱成一锅粥。你想想看,如果每个对象都要知道其他对象的存在,那代码的耦合度简直不敢想象。
中介者模式的核心思想很简单:用一个中介对象来封装一系列对象的交互。说白了,就是让对象之间不再直接“说话”,而是通过一个中间人来传达。这个中间人就是中介者。
业务场景:聊天室
聊天室是最经典的中介者模式案例。用户之间不直接通信,而是通过聊天室服务器(中介者)来转发消息。每个用户只需要知道服务器的地址,不需要知道其他用户的存在。
我在项目中遇到过类似场景——一个内部协作平台,多个模块需要互相通知状态变更。如果让模块之间直接调用,那代码会变成一团乱麻。后来我用中介者模式重构,所有模块只跟一个“事件总线”通信,清爽多了。
MVC 中的 Controller
MVC 架构里,Controller 就是 Model 和 View 的中介者。View 不直接操作 Model,Model 也不直接更新 View。所有交互都通过 Controller 来协调。这就是中介者模式的典型应用。
核心结构
中介者模式涉及以下几个角色:
- Mediator(中介者):定义通信接口,负责协调各同事对象的交互。
- ConcreteMediator(具体中介者):实现中介者接口,维护同事对象的引用,实现具体的协调逻辑。
- Colleague(同事):每个同事对象都持有中介者的引用,需要通信时调用中介者的方法。
嗯,这里要注意:同事对象之间不能有直接引用。所有通信必须经过中介者。这是模式的核心约束。
代码示例:聊天室实现
我们来看一个简单的聊天室实现。先定义中介者接口:
// 中介者接口
public interface ChatMediator {
void sendMessage(String message, User user);
void addUser(User user);
}
然后实现具体中介者——聊天室服务器:
// 具体中介者
public class ChatRoom implements ChatMediator {
private List<User> users = new ArrayList<>();
@Override
public void addUser(User user) {
users.add(user);
}
@Override
public void sendMessage(String message, User sender) {
for (User user : users) {
// 消息不发送给自己
if (user != sender) {
user.receive(message);
}
}
}
}
接下来是同事对象——用户:
// 同事类
public class User {
private String name;
private ChatMediator mediator;
public User(String name, ChatMediator mediator) {
this.name = name;
this.mediator = mediator;
}
public void send(String message) {
System.out.println(name + " 发送消息: " + message);
mediator.sendMessage(message, this);
}
public void receive(String message) {
System.out.println(name + " 收到消息: " + message);
}
}
客户端使用:
public class Client {
public static void main(String[] args) {
ChatMediator chatRoom = new ChatRoom();
User alice = new User("Alice", chatRoom);
User bob = new User("Bob", chatRoom);
User charlie = new User("Charlie", chatRoom);
chatRoom.addUser(alice);
chatRoom.addUser(bob);
chatRoom.addUser(charlie);
alice.send("大家好!");
bob.send("嗨,Alice!");
}
}
运行结果:
Alice 发送消息: 大家好!
Bob 收到消息: 大家好!
Charlie 收到消息: 大家好!
Bob 发送消息: 嗨,Alice!
Alice 收到消息: 嗨,Alice!
Charlie 收到消息: 嗨,Alice!
中介者模式的核心逻辑图
下面这张 SVG 图展示了中介者模式的核心交互逻辑:
避坑指南
我曾经在一个项目中过度使用中介者模式,结果中介者变成了一个“上帝对象”,什么逻辑都往里面塞。最后中介者本身变得臃肿不堪,维护起来比直接耦合还痛苦。
这里分享几个经验:
- 中介者不要包揽一切:只做协调和转发,不要把业务逻辑也塞进去。
- 同事对象保持简单:同事只负责自己的行为,不要依赖中介者做太多事情。
- 考虑性能:如果通信非常频繁,中介者可能成为瓶颈。这时候可以考虑事件驱动或消息队列。
核心要点:中介者模式的核心价值在于“解耦”。它让对象之间的多对多关系,变成了对象与中介者之间的一对多关系。虽然增加了一个中间层,但换来了系统的可维护性和可扩展性。
个人习惯:我一般在以下情况使用中介者模式:
- 一组对象之间通信复杂,且通信逻辑经常变化
- 想复用某个对象,但它依赖太多其他对象
- 需要集中控制对象之间的交互行为
注意:不要为了用模式而用模式。如果对象之间只有简单的两两通信,直接调用反而更清晰。中介者模式适合“多对多”的复杂场景。
实际项目中的应用
我记得在一个电商系统中,订单、库存、支付、物流等多个模块需要协同工作。如果让它们直接互相调用,那代码会变成蜘蛛网。我引入了一个“交易协调器”作为中介者,所有模块只跟协调器通信。后来新增了优惠券模块,只需要在协调器里加几行代码就行,其他模块完全不用改。
这就是中介者模式的魅力——让系统在变化中保持稳定。
说白了,中介者模式就是给对象们请了一个“和事佬”。大家有事找和事佬,别自己吵吵。这样系统才能井井有条。