一、中介者模式:对象间解耦、MVC中的中介者
中介者模式,说白了就是给一堆互相调用的对象找个「中间人」。
我刚开始做项目时,经常遇到这样的场景:几个模块之间互相持有引用,A调B,B调C,C又调A……代码改一处,牵一发动全身。后来我意识到,这种网状结构迟早会变成维护噩梦。
中介者模式就是来解决这个问题的。它把多对多的交互,转变成一对多的交互——所有对象只跟中介者通信,中介者负责协调。
1.1 什么是中介者模式
中介者模式(Mediator Pattern)定义了一个封装对象间交互行为的对象。它让对象之间不再显式引用彼此,从而降低耦合。
你想想看,现实中的房产中介就是典型例子。房东和租客不需要直接认识,中介帮他们完成信息匹配、谈判、签约。代码里的中介者也是这个道理。
1.2 模式结构
| 角色 | 职责 |
|---|---|
| Mediator(抽象中介者) | 定义通信接口,用于各同事对象之间的通信 |
| ConcreteMediator(具体中介者) | 实现中介者接口,协调各同事对象的交互逻辑 |
| Colleague(抽象同事类) | 定义同事对象的公共接口,持有中介者引用 |
| ConcreteColleague(具体同事类) | 每个同事类只知道自己的行为,不关心其他同事 |
1.3 代码示例:聊天室
我拿一个聊天室的例子来说明。用户之间发消息,如果每个用户都持有其他用户的引用,那代码会非常混乱。用中介者模式就清爽多了。
// 抽象中介者
public abstract class Mediator {
public abstract void sendMessage(String message, User user);
}
// 具体中介者 - 聊天室
public class ChatRoom extends Mediator {
private List<User> users = new ArrayList<>();
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 abstract class User {
protected Mediator mediator;
protected String name;
public User(Mediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public abstract void send(String message);
public abstract void receive(String message);
}
// 具体同事类
public class ChatUser extends User {
public ChatUser(Mediator mediator, String name) {
super(mediator, name);
}
@Override
public void send(String message) {
System.out.println(name + " 发送消息: " + message);
mediator.sendMessage(message, this);
}
@Override
public void receive(String message) {
System.out.println(name + " 收到消息: " + message);
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
ChatRoom chatRoom = new ChatRoom();
User user1 = new ChatUser(chatRoom, "张三");
User user2 = new ChatUser(chatRoom, "李四");
User user3 = new ChatUser(chatRoom, "王五");
chatRoom.addUser(user1);
chatRoom.addUser(user2);
chatRoom.addUser(user3);
user1.send("大家好!");
user2.send("欢迎新同学!");
}
}
运行结果:
张三 发送消息: 大家好!
李四 收到消息: 大家好!
王五 收到消息: 大家好!
李四 发送消息: 欢迎新同学!
张三 收到消息: 欢迎新同学!
王五 收到消息: 欢迎新同学!
你看,每个用户只跟聊天室打交道,不需要知道其他用户的存在。这就是解耦。
1.4 MVC中的中介者
说到中介者模式,就不得不提MVC架构。我个人觉得,MVC就是中介者模式最经典的实践。
- View(视图):负责展示数据,不直接操作数据源
- Controller(控制器):扮演中介者角色,接收用户输入,协调Model和View
- Model(模型):负责业务逻辑和数据,不关心谁来展示它
我在项目中遇到过这样的场景:一个表单页面,用户点击提交按钮,View需要验证数据、调用接口、更新页面状态。如果没有Controller,这些逻辑全塞在View里,代码很快就变成一坨。
用MVC之后,View只负责渲染和事件绑定,Controller负责调度,Model负责数据。各司其职,改起来也轻松。
1.5 中介者模式的应用场景
- 多个对象之间存在复杂的引用关系:比如GUI中的多个组件互相影响
- 想复用某个对象,但它的交互逻辑太复杂:把交互抽出来放到中介者里
- 系统需要解耦,让各模块独立演化:中介者模式天然支持这一点
1.6 中介者模式的优缺点
| 优点 | 缺点 |
|---|---|
| 减少类之间的直接耦合 | 中介者可能变得庞大复杂 |
| 将多对多交互简化为一对多 | 中介者出问题会影响所有同事 |
| 符合迪米特法则 | 增加了系统的复杂度 |
1.7 中介者模式与观察者模式的区别
这两个模式容易混淆。我简单说一下区别:
- 中介者模式:对象之间通过中介者通信,中介者知道所有对象
- 观察者模式:一个对象(主题)通知多个观察者,观察者之间不知道彼此
说白了,中介者模式是「点对点」的协调,观察者模式是「一对多」的通知。实际项目中,两者经常结合使用。
1.8 核心逻辑图
1.9 总结
中介者模式的核心价值就一句话:把多对多的混乱交互,变成一对多的清晰调度。
我在实际项目中,一般会在以下情况考虑使用中介者模式:
- 多个对象之间有复杂的交互逻辑
- 交互逻辑经常变化,需要集中管理
- 希望各模块能独立测试和复用
但也要注意,不要为了用模式而用模式。如果只有两三个对象交互,直接调用反而更简单。模式是工具,不是目的。
公众号:蓝海资料掘金营,微信deep3321