中介者模式(Mediator)
意图
用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
UML 图
优点
- 降低耦合度:将对象间的一对多关联转变为一对一的关联,减少对象间的依赖
- 集中控制:将交互逻辑集中到中介者中,使得交互更易于理解和维护
- 简化对象协议:用中介者和同事间的一对多交互代替多对多交互
- 对象职责分离:同事类可以更加专注于自身的业务逻辑
- 易于扩展:增加新的同事类很容易,只需修改中介者即可
缺点
- 中介者复杂性:中介者可能会变得过于复杂和庞大,成为上帝对象
- 性能问题:所有通信都通过中介者,可能成为性能瓶颈
- 单点故障:中介者出现故障会影响整个系统
- 增加系统复杂度:需要引入新的中介者类
- 过度集中化:可能将本应分布的逻辑过度集中到中介者中
代码示例
以人类和机器人的协作系统为例:
1. 中介者接口 (Mediator Interface)
// 中介者接口
public interface CollaborationMediator {void sendMessage(String message, Colleague sender);void addColleague(Colleague colleague);void mediateCollaboration(String task);
}
2. 同事类接口 (Colleague Interface)
// 同事类接口
public abstract class Colleague {protected CollaborationMediator mediator;protected String name;public Colleague(CollaborationMediator mediator, String name) {this.mediator = mediator;this.name = name;}public abstract void send(String message);public abstract void receive(String message);public abstract void performTask(String task);public String getName() {return name;}
}
3. 具体中介者 (Concrete Mediator)
// 人机协作中介者
public class HumanRobotMediator implements CollaborationMediator {private List<Colleague> colleagues = new ArrayList<>();private Map<String, List<Colleague>> specialists = new HashMap<>();@Overridepublic void addColleague(Colleague colleague) {colleagues.add(colleague);}@Overridepublic void sendMessage(String message, Colleague sender) {for (Colleague colleague : colleagues) {// 不将消息发送给自己if (colleague != sender) {colleague.receive(sender.getName() + " 说: " + message);}}}@Overridepublic void mediateCollaboration(String task) {System.out.println("中介者协调任务: " + task);// 根据任务类型分配工作if (task.contains("数据分析")) {notifySpecialists("数据分析", task);} else if (task.contains("体力劳动")) {notifySpecialists("体力劳动", task);} else if (task.contains("创意工作")) {notifySpecialists("创意工作", task);} else {// 默认广播给所有同事for (Colleague colleague : colleagues) {colleague.performTask(task);}}}public void registerSpecialty(String specialty, Colleague colleague) {specialists.computeIfAbsent(specialty, k -> new ArrayList<>()).add(colleague);}private void notifySpecialists(String specialty, String task) {List<Colleague> experts = specialists.get(specialty);if (experts != null && !experts.isEmpty()) {for (Colleague expert : experts) {expert.performTask("专项任务: " + task);}} else {System.out.println("没有找到" + specialty + "专家");}}
}
4. 具体同事类 - 人类 (Concrete Colleague - Human)
// 人类同事
public class HumanColleague extends Colleague {private Set<String> skills = new HashSet<>();public HumanColleague(CollaborationMediator mediator, String name, Set<String> skills) {super(mediator, name);this.skills.addAll(skills);this.mediator.addColleague(this);}@Overridepublic void send(String message) {System.out.println(name + " 发送消息: " + message);mediator.sendMessage(message, this);}@Overridepublic void receive(String message) {System.out.println(name + " 收到消息: " + message);}@Overridepublic void performTask(String task) {if (canPerformTask(task)) {System.out.println(name + " 正在执行任务: " + task);} else {System.out.println(name + " 无法执行任务: " + task + " (缺乏相关技能)");}}private boolean canPerformTask(String task) {for (String skill : skills) {if (task.contains(skill)) {return true;}}return false;}public void addSkill(String skill) {skills.add(skill);}
}
5. 具体同事类 - 机器人 (Concrete Colleague - Robot)
// 机器人同事
public class RobotColleague extends Colleague {private Set<String> capabilities = new HashSet<>();private int batteryLevel = 100;public RobotColleague(CollaborationMediator mediator, String name, Set<String> capabilities) {super(mediator, name);this.capabilities.addAll(capabilities);this.mediator.addColleague(this);}@Overridepublic void send(String message) {System.out.println(name + " 发送消息: " + message);mediator.sendMessage(message, this);}@Overridepublic void receive(String message) {System.out.println(name + " 收到消息: " + message);// 机器人可以自动响应某些消息if (message.contains("电池状态")) {send("电池电量: " + batteryLevel + "%");}}@Overridepublic void performTask(String task) {if (batteryLevel <= 0) {System.out.println(name + " 电量不足,无法执行任务");return;}if (canPerformTask(task)) {System.out.println(name + " 正在执行任务: " + task);batteryLevel -= 10; // 每次任务消耗10%电量} else {System.out.println(name + " 无法执行任务: " + task + " (超出能力范围)");}}private boolean canPerformTask(String task) {for (String capability : capabilities) {if (task.contains(capability)) {return true;}}return false;}public void recharge() {batteryLevel = 100;System.out.println(name + " 充电完成");}public int getBatteryLevel() {return batteryLevel;}
}
6. 客户端代码
public class MediatorPatternDemo {public static void main(String[] args) {System.out.println("=== 中介者模式演示 - 人机协作系统 ===\n");// 创建中介者HumanRobotMediator mediator = new HumanRobotMediator();// 创建人类同事HumanColleague human1 = new HumanColleague(mediator, "张三", Set.of("创意工作", "决策", "沟通"));HumanColleague human2 = new HumanColleague(mediator, "李四", Set.of("数据分析", "编程", "设计"));// 创建机器人同事RobotColleague robot1 = new RobotColleague(mediator, "机器人A", Set.of("数据分析", "计算", "报告生成"));RobotColleague robot2 = new RobotColleague(mediator, "机器人B", Set.of("体力劳动", "搬运", "装配"));// 注册专业技能mediator.registerSpecialty("数据分析", robot1);mediator.registerSpecialty("数据分析", human2);mediator.registerSpecialty("体力劳动", robot2);mediator.registerSpecialty("创意工作", human1);System.out.println("1. 同事间通过中介者通信:");human1.send("大家好,今天我们需要完成数据分析报告");System.out.println();robot1.send("我可以协助处理数据分析任务");System.out.println();System.out.println("2. 中介者协调任务分配:");mediator.mediateCollaboration("数据分析任务");System.out.println();mediator.mediateCollaboration("体力劳动任务");System.out.println();mediator.mediateCollaboration("创意设计任务");System.out.println();System.out.println("3. 机器人状态监控:");human1.send("机器人A,报告电池状态");System.out.println();System.out.println("4. 处理无法执行的任务:");mediator.mediateCollaboration("高空作业任务");System.out.println();System.out.println("5. 演示电池耗尽情况:");for (int i = 0; i < 6; i++) {robot2.performTask("搬运货物");}}
}
在Spring的应用
在Spring框架中,中介者模式的应用体现在多个方面:
-
ApplicationContext作为中介者:Spring的ApplicationContext充当了中介者的角色,管理各个Bean之间的依赖关系和交互
-
事件发布-订阅机制:Spring的事件机制是中介者模式的典型应用
// 事件发布者 applicationContext.publishEvent(new CustomEvent(this, "事件数据"));// 事件监听者 @EventListener public void handleCustomEvent(CustomEvent event) {// 处理事件 }
-
消息中间件集成:Spring Integration和Spring Messaging提供了基于中介者模式的消息通道
@Service public class IntegrationService {@Autowiredprivate MessageChannel inputChannel;public void sendMessage(Message<?> message) {inputChannel.send(message);} }
-
事务管理:Spring的事务管理器作为中介者协调多个资源的事务
总结
中介者模式通过引入一个中介对象来封装对象之间的复杂交互,有效降低了系统中类之间的耦合度。在人机协作系统的示例中,中介者负责协调人类和机器人之间的通信和任务分配,使得各个同事类可以专注于自身的职责而不需要了解其他同事的细节。
该模式特别适用于以下场景:
- 对象间存在复杂的引用关系,系统结构混乱且难以理解
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类
- 对象间的依赖关系复杂,需要集中控制这些交互
在Spring框架中,中介者模式得到了广泛的应用,特别是在事件处理、消息传递和上下文管理等方面,体现了该模式在大型框架中的实用价值。