Java设计模式之中介者模式详解
一、中介者模式核心思想
核心目标:通过中介对象封装一组对象间的交互,将网状的对象关系转变为星型结构。如同机场控制塔协调所有飞机的起降,避免飞机之间直接通信导致的混乱。
二、中介者模式类图(Mermaid)
三、代码实现示例
1. 聊天室场景
// 中介者接口
interface ChatMediator {
void sendMessage(String msg, User user);
void addUser(User user);
}
// 具体中介者:聊天室
class ChatRoom implements ChatMediator {
private List<User> users = new ArrayList<>();
public void addUser(User user) {
users.add(user);
}
public void sendMessage(String msg, User sender) {
for (User user : users) {
if (user != sender) { // 不发送给自己
user.receive(msg);
}
}
}
}
// 抽象组件
abstract class User {
protected ChatMediator mediator;
protected String name;
public User(String name, ChatMediator mediator) {
this.name = name;
this.mediator = mediator;
}
public abstract void send(String msg);
public abstract void receive(String msg);
}
// 具体组件:聊天用户
class ChatUser extends User {
public ChatUser(String name, ChatMediator mediator) {
super(name, mediator);
}
public void send(String msg) {
System.out.println(name + " 发送: " + msg);
mediator.sendMessage(msg, this);
}
public void receive(String msg) {
System.out.println(name + " 收到: " + msg);
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
ChatMediator chatRoom = new ChatRoom();
User alice = new ChatUser("Alice", chatRoom);
User bob = new ChatUser("Bob", chatRoom);
User charlie = new ChatUser("Charlie", chatRoom);
chatRoom.addUser(alice);
chatRoom.addUser(bob);
chatRoom.addUser(charlie);
alice.send("大家好!");
/* 输出:
Alice 发送: 大家好!
Bob 收到: 大家好!
Charlie 收到: 大家好! */
}
}
四、模式优缺点分析
✅ 优势
- 解耦对象关系:组件间无需直接引用
- 简化交互协议:统一通过中介者通信
- 集中控制逻辑:交互规则在中介者中维护
- 减少子类数量:避免为不同交互创建大量子类
❌ 缺点
- 中介者可能复杂:随着交互增加,中介者可能成为"上帝对象"
- 性能瓶颈:所有通信经过中介者,可能成为系统瓶颈
- 过度设计风险:简单交互场景不适用
五、典型应用场景
- GUI组件交互:表单验证(输入框、按钮、标签联动)
- 聊天系统:群聊消息分发
- 航空管制:协调飞机起降
- 分布式系统:服务注册与发现(如Eureka)
- 工作流引擎:任务节点间的协调
- 游戏开发:NPC行为协调
六、Mermaid序列图(交互流程)
七、中介者模式 vs 其他模式
对比模式 | 核心区别 |
---|---|
观察者模式 | 单向通知,不处理响应 |
外观模式 | 简化子系统接口,不处理组件间交互 |
代理模式 | 控制单个对象访问 |
八、实际框架应用案例
1. Java Message Service (JMS)
classDiagram
class ConnectionFactory
class Connection
class Session
class MessageProducer
class MessageConsumer
ConnectionFactory --> Connection : 创建
Connection --> Session : 创建
Session --> MessageProducer : 创建
Session --> MessageConsumer : 创建
MessageProducer --> Message : 发送
MessageConsumer --> Message : 接收
note for ConnectionFactory "作为中介者协调\n生产者与消费者"
2. Spring框架中的ApplicationContext
@Component
class ServiceA {
@Autowired
private ApplicationContext context; // 中介者
public void doSomething() {
// 通过中介者获取其他组件
ServiceB serviceB = context.getBean(ServiceB.class);
serviceB.process();
}
}
九、高级应用技巧
1. 中介者分层设计
2. 事件总线(简化版)
class EventBusMediator {
private Map<Class<?>, List<Consumer<Object>>> handlers = new HashMap<>();
public <T> void subscribe(Class<T> eventType, Consumer<T> handler) {
handlers.computeIfAbsent(eventType, k -> new ArrayList<>())
.add((Consumer<Object>) handler);
}
public void publish(Object event) {
List<Consumer<Object>> eventHandlers = handlers.get(event.getClass());
if (eventHandlers != null) {
eventHandlers.forEach(handler -> handler.accept(event));
}
}
}
// 使用示例
EventBusMediator bus = new EventBusMediator();
bus.subscribe(String.class, msg -> System.out.println("处理字符串: " + msg));
bus.publish("测试消息");
十、常见问题解答
Q1:如何避免中介者变成"上帝对象"?
- 职责拆分:创建多个专业中介者(如登录中介者、支付中介者)
- 使用状态模式:让中介者根据状态改变行为
- 结合命令模式:将操作封装为命令对象
Q2:中介者模式如何支持异步?
class AsyncMediator {
private Executor executor = Executors.newCachedThreadPool();
public void mediate(Runnable task) {
executor.execute(task);
}
}
Q3:如何处理组件间的双向通信?
在中介者中实现回调机制:
interface Callback {
void onComplete(Object result);
}
class ComponentA {
void request(Mediator mediator, Callback callback) {
mediator.processRequest(this, callback);
}
}
class Mediator {
void processRequest(ComponentA comp, Callback callback) {
// 处理请求...
callback.onComplete(result);
}
}
如果你觉得文章对你有帮助的话,请帮忙点点关注吧!谢谢啦