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)
classDiagramclass ConnectionFactoryclass Connectionclass Sessionclass MessageProducerclass MessageConsumerConnectionFactory --> 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);}
}
如果你觉得文章对你有帮助的话,请帮忙点点关注吧!谢谢啦