中介者模式 (Mediator Pattern)
概述 (Overview)
中介者模式是一种行为型设计模式,它定义了一个对象来封装一组对象之间的交互方式。中介者使对象之间不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
Mediator Pattern is a behavioral design pattern that defines how a set of objects interact. It promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
意图 (Intent)
定义一个对象来封装一组对象的交互。中介者使对象之间不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
适用场景 (When to Use)
- 当一组对象以定义良好但复杂的方式进行通信时
- 当需要支持多个对象之间的复杂交互,但又不想让这些对象相互显式引用时
- 当需要定制一个分布在多个类中的行为,而又不想生成太多子类时
- 当对象之间的交互导致难以理解和维护的依赖关系时
- 当需要集中控制对象之间的交互逻辑时
- 当需要重用对象,但对象之间的依赖关系限制了它们的重用时
结构 (Structure)
基础中介者模式结构图 (Basic Mediator Pattern Structure)
实现方式 (Implementation Approaches)
1. 经典中介者模式 (Classic Mediator Pattern)
// 中介者接口 - Mediator Interface
public interface ChatMediator {
void sendMessage(String message, User user);
void addUser(User user);
void removeUser(User user);
}
// 具体中介者 - Concrete Mediator
public class ChatRoom implements ChatMediator {
private List<User> users;
private String roomName;
public ChatRoom(String roomName) {
this.roomName = roomName;
this.users = new ArrayList<>();
}
@Override
public void sendMessage(String message, User sender) {
System.out.println("\n[" + roomName + "] " + sender.getName() + " 发送消息: " + message);
// 将消息发送给所有其他用户(不包括发送者)
for (User user : users) {
if (user != sender) {
user.receiveMessage(message, sender.getName());
}
}
// 记录消息历史
logMessage(message, sender);
}
@Override
public void addUser(User user) {
users.add(user);
System.out.println(user.getName() + " 加入了聊天室 [" + roomName + "]");
// 通知其他用户有新成员加入
for (User u : users) {
if (u != user) {
u.receiveMessage(user.getName() + " 加入了聊天室", "系统");
}
}
}
@Override
public void removeUser(User user) {
users.remove(user);
System.out.println(user.getName() + " 离开了聊天室 [" + roomName + "]");
// 通知其他用户有成员离开
for (User u : users) {
u.receiveMessage(user.getName() + " 离开了聊天室", "系统");
}
}
private void logMessage(String message, User sender) {
System.out.println("[日志] " + new Date() + " - " + sender.getName() + ": " + message);
}
public List<User> getUsers() {
return new ArrayList<>(users);
}
}
// 同事类 - Colleague Class
public abstract class User {
protected ChatMediator mediator;
protected String name;
public User(ChatMediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public abstract void sendMessage(String message);
public abstract void receiveMessage(String message, String senderName);
public String getName() {
return name;
}
}
// 具体同事类 - Concrete Colleague Classes
public class RegularUser extends User {
public RegularUser(ChatMediator mediator, String name) {
super(mediator, name);
}
@Override
public void sendMessage(String message) {
System.out.println("\n[" + name + "] 准备发送消息: " + message);
mediator.sendMessage(message, this);
}
@Override
public void receiveMessage(String message, String senderName) {
System.out.println("[" + name + "] 收到来自 [" + senderName + "] 的消息: " + message);
}
}
public class PremiumUser extends User {
private boolean notificationsEnabled = true;
public PremiumUser(ChatMediator mediator, String name) {
super(mediator, name);
}
@Override
public void sendMessage(String message) {
System.out.println("\n[" + name + "] (高级用户) 发送消息: " + message);
mediator.sendMessage(message, this);
}
@Override
public void receiveMessage(String message, String senderName) {
if (notificationsEnabled) {
System.out.println("[" + name + "] (高级用户) 收到来自 [" + senderName + "] 的消息: " + message);
// 高级用户可以收到特殊通知
if (senderName.equals("系统")) {
System.out.println("[" + name + "] 收到系统通知!");
}
}
}
public void setNotificationsEnabled(boolean enabled) {
this.notificationsEnabled = enabled;
}
}
public class AdminUser extends User {
public AdminUser(ChatMediator mediator, String name) {
super(mediator, name);
}
@Override
public void sendMessage(String message) {
System.out.println("\n[" + name + "] (管理员) 发送消息: " + message);
mediator.sendMessage(message, this);
}
@Override
public void receiveMessage(String message, String senderName) {
System.out.println("[" + name + "] (管理员) 收到来自 [" + senderName + "] 的消息: " + message);
}
// 管理员特有的功能
public void kickUser(String userName) {
System.out.println("\n[" + name + "] (管理员) 踢出用户: " + userName);
ChatRoom room = (ChatRoom) mediator;
List<User> users = room.getUsers();
for (User user : users) {
if (user.getName().equals(userName)) {
mediator.removeUser(user);
break;
}
}
}
public void broadcastSystemMessage(String message) {
System.out.println("\n[" + name + "] (管理员) 广播系统消息: " + message);
mediator.sendMessage("[系统公告] " + message, this);
}
}
// 客户端使用 - Client Usage
public class ChatRoomDemo {
public static void main(String[] args) {
System.out.println("=== 聊天室中介者模式演示 ===");
// 创建聊天室(中介者)
ChatRoom chatRoom = new ChatRoom("技术交流群");
// 创建用户(同事)
User user1 = new RegularUser(chatRoom, "张三");
User user2 = new RegularUser(chatRoom, "李四");
User user3 = new PremiumUser(chatRoom, "王五");
User admin = new AdminUser(chatRoom, "管理员");
// 用户加入聊天室
chatRoom.addUser(user1);
chatRoom.addUser(user2);
chatRoom.addUser(user3);
chatRoom.addUser(admin);
// 用户发送消息
user1.sendMessage("大家好!");
user2.sendMessage("欢迎欢迎!");
user3.sendMessage("很高兴加入这个群");
// 管理员功能
((AdminUser) admin).broadcastSystemMessage("请大家遵守群规,文明交流");
// 模拟用户离开
chatRoom.removeUser(user2);
// 继续聊天
user1.sendMessage("李四怎么走了?");
user3.sendMessage("可能有事吧");
System.out.println("\n=== 演示完成 ===");
}
}
2. 事件驱动中介者模式 (Event-Driven Mediator Pattern)
// 事件类型枚举 - Event Type Enum
public enum EventType {
USER_LOGIN, USER_LOGOUT, USER_MESSAGE, SYSTEM_ALERT, FILE_UPLOAD, FILE_DOWNLOAD
}
// 事件类 - Event Class
public class Event {
private EventType type;
private Object data;
private String source;
private Date timestamp;
public Event(EventType type, Object data, String source) {
this.type = type;
this.data = data;
this.source = source;
this.timestamp = new Date();
}
// Getters
public EventType getType() { return type; }
public Object getData() { return data; }
public String getSource() { return source; }
public Date getTimestamp() { return timestamp; }
@Override
public String toString() {
return String.format("Event{type=%s, source='%s', timestamp=%s}", type, source, timestamp);
}
}
// 事件监听器接口 - Event Listener Interface
public interface EventListener {
void onEvent(Event event);
boolean supports(EventType eventType);
}
// 具体事件监听器 - Concrete Event Listeners
public class UserEventListener implements EventListener {
@Override
public void onEvent(Event event) {
switch (event.getType()) {
case USER_LOGIN:
System.out.println("用户事件监听器:用户登录 - " + event.getData());
break;
case USER_LOGOUT:
System.out.println("用户事件监听器:用户登出 - " + event.getData());
break;
case USER_MESSAGE:
System.out.println("用户事件监听器:用户消息 - " + event.getData());
break;
default:
// 不处理其他类型的事件
break;
}
}
@Override
public boolean supports(EventType eventType) {
return eventType == EventType.USER_LOGIN ||
eventType == EventType.USER_LOGOUT ||
eventType == EventType.USER_MESSAGE;
}
}
public class SystemEventListener implements EventListener {
@Override
public void onEvent(Event event) {
switch (event.getType()) {
case SYSTEM_ALERT:
System.out.println("系统事件监听器:系统警报 - " + event.getData());
handleSystemAlert(event.getData());
break;
default:
break;
}
}
@Override
public boolean supports(EventType eventType) {
return eventType == EventType.SYSTEM_ALERT;
}
private void handleSystemAlert(Object data) {
System.out.println("处理系统警报: " + data);
// 可以在这里添加发送邮件、短信等通知逻辑
}
}
public class FileEventListener implements EventListener {
@Override
public void onEvent(Event event) {
switch (event.getType()) {
case FILE_UPLOAD:
System.out.println("文件事件监听器:文件上传 - " + event.getData());
handleFileUpload(event.getData());
break;
case FILE_DOWNLOAD:
System.out.println("文件事件监听器:文件下载 - " + event.getData());
handleFileDownload(event.getData());
break;
default:
break;
}
}
@Override
public boolean supports(EventType eventType) {
return eventType == EventType.FILE_UPLOAD || eventType == EventType.FILE_DOWNLOAD;
}
private void handleFileUpload(Object data) {
System.out.println("处理文件上传: " + data);
// 可以进行病毒扫描、文件大小检查等
}
private void handleFileDownload(Object data) {
System.out.println("处理文件下载: " + data);
// 可以记录下载日志、检查权限等
}
}
// 事件总线(中介者)- Event Bus (Mediator)
public class EventBus implements EventMediator {
private Map<EventType, List<EventListener>> listeners;
private boolean asyncProcessing;
private ExecutorService executorService;
public EventBus(boolean asyncProcessing) {
this.asyncProcessing = asyncProcessing;
this.listeners = new ConcurrentHashMap<>();
if (asyncProcessing) {
this.executorService = Executors.newCachedThreadPool();
}
// 初始化事件类型映射
for (EventType type : EventType.values()) {
listeners.put(type, new CopyOnWriteArrayList<>());
}
}
@Override
public void publishEvent(Event event) {
System.out.println("\n事件总线发布事件: " + event);
List<EventListener> eventListeners = listeners.get(event.getType());
if (asyncProcessing) {
// 异步处理事件
for (EventListener listener : eventListeners) {
executorService.submit(() -> {
try {
if (listener.supports(event.getType())) {
listener.onEvent(event);
}
} catch (Exception e) {
System.err.println("事件监听器处理失败: " + e.getMessage());
}
});
}
} else {
// 同步处理事件
for (EventListener listener : eventListeners) {
try {
if (listener.supports(event.getType())) {
listener.onEvent(event);
}
} catch (Exception e) {
System.err.println("事件监听器处理失败: " + e.getMessage());
}
}
}
}
@Override
public void subscribe(EventType eventType, EventListener listener) {
listeners.get(eventType).add(listener);
System.out.println("事件监听器订阅事件类型: " + eventType);
}
@Override
public void unsubscribe(EventType eventType, EventListener listener) {
listeners.get(eventType).remove(listener);
System.out.println("事件监听器取消订阅事件类型: " + eventType);
}
@Override
public void shutdown() {
if (executorService != null) {
executorService.shutdown();
try {
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
}
// 事件源 - Event Source
public class UserService {
private EventMediator eventBus;
public UserService(EventMediator eventBus) {
this.eventBus = eventBus;
}
public void userLogin(String username) {
System.out.println("\n用户服务:用户登录 - " + username);
Event event = new Event(EventType.USER_LOGIN, username, "UserService");
eventBus.publishEvent(event);
}
public void userLogout(String username) {
System.out.println("\n用户服务:用户登出 - " + username);
Event event = new Event(EventType.USER_LOGOUT, username, "UserService");
eventBus.publishEvent(event);
}
public void sendUserMessage(String username, String message) {
System.out.println("\n用户服务:用户消息 - " + username + ": " + message);
Map<String, String> messageData = new HashMap<>();
messageData.put("username", username);
messageData.put("message", message);
Event event = new Event(EventType.USER_MESSAGE, messageData, "UserService");
eventBus.publishEvent(event);
}
}
public class FileService {
private EventMediator eventBus;
public FileService(EventMediator eventBus) {
this.eventBus = eventBus;
}
public void uploadFile(String filename, long size) {
System.out.println("\n文件服务:文件上传 - " + filename + " (" + size + " bytes)");
Map<String, Object> fileData = new HashMap<>();
fileData.put("filename", filename);
fileData.put("size", size);
Event event = new Event(EventType.FILE_UPLOAD, fileData, "FileService");
eventBus.publishEvent(event);
}
public void downloadFile(String filename) {
System.out.println("\n文件服务:文件下载 - " + filename);
Event event = new Event(EventType.FILE_DOWNLOAD, filename, "FileService");
eventBus.publishEvent(event);
}
}
public class SystemMonitor {
private EventMediator eventBus;
public SystemMonitor(EventMediator eventBus) {
this.eventBus = eventBus;
}
public void sendAlert(String alertMessage) {
System.out.println("\n系统监控:发送警报 - " + alertMessage);
Event event = new Event(EventType.SYSTEM_ALERT, alertMessage, "SystemMonitor");
eventBus.publishEvent(event);
}
}
// 客户端使用 - Client Usage
public class EventDrivenMediatorDemo {
public static void main(String[] args) {
System.out.println("=== 事件驱动中介者模式演示 ===");
// 创建事件总线(中介者)
EventBus eventBus = new EventBus(true); // 使用异步处理
// 创建事件监听器
EventListener userListener = new UserEventListener();
EventListener systemListener = new SystemEventListener();
EventListener fileListener = new FileEventListener();
// 订阅事件
eventBus.subscribe(EventType.USER_LOGIN, userListener);
eventBus.subscribe(EventType.USER_LOGOUT, userListener);
eventBus.subscribe(EventType.USER_MESSAGE, userListener);
eventBus.subscribe(EventType.SYSTEM_ALERT, systemListener);
eventBus.subscribe(EventType.FILE_UPLOAD, fileListener);
eventBus.subscribe(EventType.FILE_DOWNLOAD, fileListener);
// 创建事件源
UserService userService = new UserService(eventBus);
FileService fileService = new FileService(eventBus);
SystemMonitor systemMonitor = new SystemMonitor(eventBus);
// 模拟各种事件
System.out.println("\n--- 模拟用户活动 ---");
userService.userLogin("张三");
userService.sendUserMessage("张三", "大家好!");
fileService.uploadFile("document.pdf", 1024 * 1024);
systemMonitor.sendAlert("CPU使用率过高");
userService.userLogout("张三");
fileService.downloadFile("report.xlsx");
// 等待异步处理完成
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 清理资源
eventBus.shutdown();
System.out.println("\n=== 事件驱动中介者模式演示完成 ===");
}
}
3. GUI组件中介者模式 (GUI Component Mediator Pattern)
// GUI组件中介者接口 - GUI Component Mediator Interface
public interface DialogMediator {
void componentChanged(Component component);
void registerComponent(Component component);
}
// 具体GUI中介者 - Concrete GUI Mediator
public class LoginDialog implements DialogMediator {
private JTextField usernameField;
private JPasswordField passwordField;
private JCheckBox rememberMeCheckbox;
private JButton loginButton;
private JButton cancelButton;
private JLabel statusLabel;
public LoginDialog() {
createComponents();
setupLayout();
setupEventHandlers();
}
private void createComponents() {
usernameField = new JTextField(15);
passwordField = new JPasswordField(15);
rememberMeCheckbox = new JCheckBox("记住我");
loginButton = new JButton("登录");
cancelButton = new JButton("取消");
statusLabel = new JLabel("请输入用户名和密码");
// 注册组件到中介者
registerComponent(usernameField);
registerComponent(passwordField);
registerComponent(rememberMeCheckbox);
registerComponent(loginButton);
registerComponent(cancelButton);
}
private void setupLayout() {
JFrame frame = new JFrame("登录对话框");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
// 用户名
gbc.gridx = 0; gbc.gridy = 0;
mainPanel.add(new JLabel("用户名:"), gbc);
gbc.gridx = 1;
mainPanel.add(usernameField, gbc);
// 密码
gbc.gridx = 0; gbc.gridy = 1;
mainPanel.add(new JLabel("密码:"), gbc);
gbc.gridx = 1;
mainPanel.add(passwordField, gbc);
// 记住我
gbc.gridx = 1; gbc.gridy = 2;
mainPanel.add(rememberMeCheckbox, gbc);
// 状态标签
gbc.gridx = 0; gbc.gridy = 3; gbc.gridwidth = 2;
mainPanel.add(statusLabel, gbc);
// 按钮面板
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
buttonPanel.add(loginButton);
buttonPanel.add(cancelButton);
gbc.gridx = 0; gbc.gridy = 4; gbc.gridwidth = 2;
mainPanel.add(buttonPanel, gbc);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void setupEventHandlers() {
loginButton.addActionListener(e -> handleLogin());
cancelButton.addActionListener(e -> handleCancel());
}
@Override
public void registerComponent(Component component) {
// 为组件添加事件监听器
if (component instanceof JTextField) {
((JTextField) component).getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
componentChanged(component);
}
@Override
public void removeUpdate(DocumentEvent e) {
componentChanged(component);
}
@Override
public void changedUpdate(DocumentEvent e) {
componentChanged(component);
}
});
} else if (component instanceof JCheckBox) {
((JCheckBox) component).addItemListener(e -> componentChanged(component));
}
}
@Override
public void componentChanged(Component component) {
System.out.println("组件状态改变: " + component.getClass().getSimpleName());
// 根据组件状态更新其他组件
if (component == usernameField || component == passwordField) {
updateLoginButtonState();
updateStatusLabel();
} else if (component == rememberMeCheckbox) {
handleRememberMeChange();
}
}
private void updateLoginButtonState() {
String username = usernameField.getText().trim();
String password = new String(passwordField.getPassword());
// 只有当用户名和密码都不为空时才启用登录按钮
boolean enabled = !username.isEmpty() && !password.isEmpty();
loginButton.setEnabled(enabled);
System.out.println("登录按钮状态更新: " + (enabled ? "启用" : "禁用"));
}
private void updateStatusLabel() {
String username = usernameField.getText().trim();
String password = new String(passwordField.getPassword());
if (username.isEmpty() && password.isEmpty()) {
statusLabel.setText("请输入用户名和密码");
} else if (username.isEmpty()) {
statusLabel.setText("请输入用户名");
} else if (password.isEmpty()) {
statusLabel.setText("请输入密码");
} else {
statusLabel.setText("准备就绪,可以点击登录");
}
statusLabel.setForeground(Color.BLACK);
}
private void handleRememberMeChange() {
boolean selected = rememberMeCheckbox.isSelected();
System.out.println("记住我选项: " + (selected ? "选中" : "未选中"));
// 可以在这里添加记住密码的逻辑
if (selected) {
statusLabel.setText("将记住您的登录信息");
} else {
statusLabel.setText("不会记住您的登录信息");
}
}
private void handleLogin() {
String username = usernameField.getText().trim();
String password = new String(passwordField.getPassword());
boolean rememberMe = rememberMeCheckbox.isSelected();
System.out.println("\n处理登录:");
System.out.println("用户名: " + username);
System.out.println("密码: " + password.replaceAll(".", "*"));
System.out.println("记住我: " + rememberMe);
// 模拟登录验证
if ("admin".equals(username) && "password".equals(password)) {
statusLabel.setText("登录成功!");
statusLabel.setForeground(Color.GREEN);
JOptionPane.showMessageDialog(null, "登录成功!", "成功", JOptionPane.INFORMATION_MESSAGE);
} else {
statusLabel.setText("用户名或密码错误");
statusLabel.setForeground(Color.RED);
JOptionPane.showMessageDialog(null, "用户名或密码错误", "错误", JOptionPane.ERROR_MESSAGE);
}
}
private void handleCancel() {
System.out.println("\n用户点击取消按钮");
System.exit(0);
}
}
// 客户端使用 - Client Usage
public class GuiMediatorDemo {
public static void main(String[] args) {
System.out.println("=== GUI组件中介者模式演示 ===");
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeel());
} catch (Exception e) {
e.printStackTrace();
}
new LoginDialog();
System.out.println("登录对话框已启动,可以测试以下功能:");
System.out.println("1. 输入用户名和密码,观察登录按钮状态变化");
System.out.println("2. 切换'记住我'复选框,观察状态标签变化");
System.out.println("3. 使用admin/password登录,测试登录功能");
System.out.println("4. 观察控制台输出,了解组件间的交互");
});
}
}
框架源码中的应用 (Framework Applications)
1. Java Timer - Timer类
// Java Timer中的中介者模式应用
// Java Timer Mediator Pattern Application
// 自定义任务 - Custom Task
public class CustomTimerTask extends TimerTask {
private String taskName;
private Runnable task;
public CustomTimerTask(String taskName, Runnable task) {
this.taskName = taskName;
this.task = task;
}
@Override
public void run() {
System.out.println("[" + new Date() + "] 执行任务: " + taskName);
try {
task.run();
System.out.println("任务执行成功: " + taskName);
} catch (Exception e) {
System.err.println("任务执行失败: " + taskName + ", 错误: " + e.getMessage());
}
}
public String getTaskName() {
return taskName;
}
}
// 任务调度器 - Task Scheduler (Mediator)
public class TaskScheduler {
private Timer timer;
private Map<String, CustomTimerTask> scheduledTasks;
public TaskScheduler() {
this.timer = new Timer("TaskScheduler", true); // 作为守护线程
this.scheduledTasks = new ConcurrentHashMap<>();
}
// 一次性任务
public void scheduleOnce(String taskName, Runnable task, long delay) {
CustomTimerTask timerTask = new CustomTimerTask(taskName, task);
timer.schedule(timerTask, delay);
scheduledTasks.put(taskName, timerTask);
System.out.println("安排一次性任务: " + taskName + ", 延迟: " + delay + "ms");
}
// 重复执行任务
public void scheduleRepeat(String taskName, Runnable task, long delay, long period) {
CustomTimerTask timerTask = new CustomTimerTask(taskName, task);
timer.scheduleAtFixedRate(timerTask, delay, period);
scheduledTasks.put(taskName, timerTask);
System.out.println("安排重复任务: " + taskName + ", 延迟: " + delay + "ms, 周期: " + period + "ms");
}
// 取消任务
public boolean cancelTask(String taskName) {
CustomTimerTask task = scheduledTasks.get(taskName);
if (task != null) {
boolean cancelled = task.cancel();
if (cancelled) {
scheduledTasks.remove(taskName);
System.out.println("取消任务: " + taskName);
}
return cancelled;
}
return false;
}
// 取消所有任务
public void cancelAllTasks() {
for (String taskName : new ArrayList<>(scheduledTasks.keySet())) {
cancelTask(taskName);
}
}
// 关闭调度器
public void shutdown() {
System.out.println("关闭任务调度器...");
cancelAllTasks();
timer.cancel();
System.out.println("任务调度器已关闭");
}
public List<String> getScheduledTasks() {
return new ArrayList<>(scheduledTasks.keySet());
}
}
// 任务执行器 - Task Executor (Colleague)
public class DataBackupTask implements Runnable {
private String backupPath;
public DataBackupTask(String backupPath) {
this.backupPath = backupPath;
}
@Override
public void run() {
System.out.println("开始数据备份到: " + backupPath);
// 模拟备份过程
try {
Thread.sleep(1000); // 模拟备份时间
System.out.println("数据备份完成: " + backupPath);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("数据备份被中断: " + backupPath);
}
}
}
public class EmailNotificationTask implements Runnable {
private String recipient;
private String subject;
private String content;
public EmailNotificationTask(String recipient, String subject, String content) {
this.recipient = recipient;
this.subject = subject;
this.content = content;
}
@Override
public void run() {
System.out.println("发送邮件通知:");
System.out.println("收件人: " + recipient);
System.out.println("主题: " + subject);
System.out.println("内容: " + content);
// 模拟邮件发送
try {
Thread.sleep(500); // 模拟发送时间
System.out.println("邮件发送完成: " + subject);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("邮件发送被中断: " + subject);
}
}
}
public class SystemMonitorTask implements Runnable {
private String metric;
public SystemMonitorTask(String metric) {
this.metric = metric;
}
@Override
public void run() {
System.out.println("监控系统指标: " + metric);
// 模拟监控过程
double value = Math.random() * 100;
System.out.printf("当前%s值: %.2f%n", metric, value);
if (value > 80) {
System.out.println("警告: " + metric + " 超过阈值!");
}
}
}
// 客户端使用 - Client Usage
public class JavaTimerMediatorDemo {
public static void main(String[] args) {
System.out.println("=== Java Timer中介者模式演示 ===");
TaskScheduler scheduler = new TaskScheduler();
// 安排一次性任务
scheduler.scheduleOnce("初始化任务", () -> {
System.out.println("系统初始化完成");
}, 1000);
// 安排重复任务
scheduler.scheduleRepeat("数据备份", new DataBackupTask("/backup/data"), 2000, 5000);
scheduler.scheduleRepeat("邮件通知", new EmailNotificationTask("admin@example.com", "系统状态", "系统运行正常"), 3000, 10000);
scheduler.scheduleRepeat("系统监控", new SystemMonitorTask("CPU使用率"), 1000, 3000);
// 让任务运行一段时间
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 取消特定任务
scheduler.cancelTask("邮件通知");
// 继续运行一段时间
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 关闭调度器
scheduler.shutdown();
System.out.println("\n=== Java Timer中介者模式演示完成 ===");
}
}
2. Spring Framework - ApplicationContext
// Spring Framework中的ApplicationContext中介者模式应用
// Spring Framework ApplicationContext Mediator Pattern Application
// 自定义事件 - Custom Event
public class UserRegistrationEvent extends ApplicationEvent {
private String username;
private String email;
public UserRegistrationEvent(Object source, String username, String email) {
super(source);
this.username = username;
this.email = email;
}
public String getUsername() { return username; }
public String getEmail() { return email; }
}
public class OrderPlacedEvent extends ApplicationEvent {
private String orderId;
private String userId;
private BigDecimal amount;
public OrderPlacedEvent(Object source, String orderId, String userId, BigDecimal amount) {
super(source);
this.orderId = orderId;
this.userId = userId;
this.amount = amount;
}
public String getOrderId() { return orderId; }
public String getUserId() { return userId; }
public BigDecimal getAmount() { return amount; }
}
// 事件监听器 - Event Listeners
@Component
public class EmailNotificationListener implements ApplicationListener<UserRegistrationEvent> {
private static final Logger logger = LoggerFactory.getLogger(EmailNotificationListener.class);
@Override
public void onApplicationEvent(UserRegistrationEvent event) {
logger.info("邮件通知监听器:用户注册 - username: {}, email: {}",
event.getUsername(), event.getEmail());
// 模拟发送欢迎邮件
try {
Thread.sleep(1000); // 模拟邮件发送时间
logger.info("欢迎邮件发送成功给: {}", event.getEmail());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("邮件发送被中断", e);
}
}
}
@Component
public class SmsNotificationListener implements ApplicationListener<UserRegistrationEvent> {
private static final Logger logger = LoggerFactory.getLogger(SmsNotificationListener.class);
@Override
public void onApplicationEvent(UserRegistrationEvent event) {
logger.info("短信通知监听器:用户注册 - username: {}", event.getUsername());
// 模拟发送短信
try {
Thread.sleep(500); // 模拟短信发送时间
logger.info("注册短信发送成功给: {}", event.getUsername());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("短信发送被中断", e);
}
}
}
@Component
public class OrderProcessingListener implements ApplicationListener<OrderPlacedEvent> {
private static final Logger logger = LoggerFactory.getLogger(OrderProcessingListener.class);
@Override
public void onApplicationEvent(OrderPlacedEvent event) {
logger.info("订单处理监听器:订单已创建 - orderId: {}, userId: {}, amount: {}",
event.getOrderId(), event.getUserId(), event.getAmount());
// 模拟订单处理
try {
Thread.sleep(2000); // 模拟处理时间
logger.info("订单处理完成: {}", event.getOrderId());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("订单处理被中断", e);
}
}
}
@Component
public class InventoryUpdateListener implements ApplicationListener<OrderPlacedEvent> {
private static final Logger logger = LoggerFactory.getLogger(InventoryUpdateListener.class);
@Override
public void onApplicationEvent(OrderPlacedEvent event) {
logger.info("库存更新监听器:更新库存 - orderId: {}", event.getOrderId());
// 模拟库存更新
try {
Thread.sleep(800); // 模拟更新时间
logger.info("库存更新完成 for order: {}", event.getOrderId());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("库存更新被中断", e);
}
}
}
// 事件发布服务 - Event Publishing Service
@Service
public class UserService {
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
private final ApplicationEventPublisher eventPublisher;
@Autowired
public UserService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void registerUser(String username, String email) {
logger.info("用户服务:注册用户 - username: {}, email: {}", username, email);
// 模拟用户注册逻辑
try {
Thread.sleep(100); // 模拟处理时间
// 发布用户注册事件
UserRegistrationEvent event = new UserRegistrationEvent(this, username, email);
eventPublisher.publishEvent(event);
logger.info("用户注册完成: {}", username);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("用户注册被中断", e);
}
}
}
@Service
public class OrderService {
private static final Logger logger = LoggerFactory.getLogger(OrderService.class);
private final ApplicationEventPublisher eventPublisher;
@Autowired
public OrderService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void placeOrder(String userId, BigDecimal amount) {
String orderId = "ORDER-" + System.currentTimeMillis();
logger.info("订单服务:创建订单 - orderId: {}, userId: {}, amount: {}", orderId, userId, amount);
// 模拟订单创建逻辑
try {
Thread.sleep(200); // 模拟处理时间
// 发布订单创建事件
OrderPlacedEvent event = new OrderPlacedEvent(this, orderId, userId, amount);
eventPublisher.publishEvent(event);
logger.info("订单创建完成: {}", orderId);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("订单创建被中断", e);
}
}
}
// 客户端使用 - Client Usage
@SpringBootApplication
public class SpringEventMediatorDemo {
public static void main(String[] args) {
SpringApplication.run(SpringEventMediatorDemo.class, args);
System.out.println("=== Spring ApplicationContext中介者模式演示 ===");
System.out.println("启动Spring Boot应用,测试事件发布/订阅功能");
}
@Component
public static class EventMediatorDemoRunner implements CommandLineRunner {
@Autowired
private UserService userService;
@Autowired
private OrderService orderService;
@Override
public void run(String... args) throws Exception {
System.out.println("\n--- 开始Spring事件中介者模式演示 ---");
// 演示用户注册事件
System.out.println("\n--- 演示用户注册事件 ---");
userService.registerUser("张三", "zhangsan@example.com");
userService.registerUser("李四", "lisi@example.com");
// 等待事件处理完成
Thread.sleep(2000);
// 演示订单创建事件
System.out.println("\n--- 演示订单创建事件 ---");
orderService.placeOrder("USER-123", new BigDecimal("299.99"));
orderService.placeOrder("USER-456", new BigDecimal("599.99"));
// 等待事件处理完成
Thread.sleep(3000);
System.out.println("\nSpring事件中介者模式演示完成");
}
}
}
中介者模式与其他模式比较 (Comparison with Other Patterns)
| 特性 | 中介者模式 | 观察者模式 | 责任链模式 | 外观模式 |
|---|---|---|---|---|
| 目的 | 对象交互解耦 | 事件通知 | 请求传递 | 接口简化 |
| 关注点 | 交互集中化 | 状态变化通知 | 处理链 | 子系统封装 |
| 使用场景 | 复杂对象交互 | 发布-订阅 | 多级处理 | 简化接口 |
| 结构特点 | 中介者协调 | 观察者注册 | 链式结构 | 统一接口 |
| 控制方式 | 集中控制 | 事件广播 | 链式传递 | 门面封装 |
最佳实践 (Best Practices)
1. 中介者设计 (Mediator Design)
- 保持中介者的职责单一,避免成为"上帝对象"
- 明确定义同事对象之间的交互协议
- 考虑中介者的可扩展性和可维护性
2. 同事对象设计 (Colleague Design)
- 保持同事对象的独立性
- 避免同事对象直接相互引用
- 确保同事对象只与中介者通信
3. 交互协议设计 (Interaction Protocol Design)
- 定义清晰的交互接口和消息格式
- 考虑支持同步和异步交互
- 处理好错误和异常情况
4. 性能优化 (Performance Optimization)
- 避免中介者成为性能瓶颈
- 考虑使用异步处理提高响应速度
- 合理使用缓存和批处理技术
5. 可测试性 (Testability)
- 设计易于测试的中介者和同事对象
- 使用依赖注入提高可测试性
- 考虑使用模拟对象进行单元测试
优缺点 (Pros and Cons)
优点 (Advantages)
- 降低耦合度:减少了对象之间的直接依赖关系
- 集中控制:将交互逻辑集中在中介者中
- 易于维护:修改交互逻辑只需修改中介者
- 支持复用:同事对象可以更容易地被复用
- 简化对象:同事对象只需要了解中介者
缺点 (Disadvantages)
- 中介者复杂化:中介者可能变得过于复杂
- 单点故障:中介者出现问题会影响整个系统
- 性能开销:通过中介者转发消息可能带来性能损失
- 设计难度:需要仔细设计中介者的接口和逻辑
- 过度集中:可能导致逻辑过度集中在中介者中
实际应用建议 (Practical Application Tips)
1. 适度使用
- 只在对象交互复杂时使用中介者模式
- 避免过度使用导致中介者过于复杂
- 考虑其他模式如观察者模式作为替代
2. 分层设计
- 考虑使用多层中介者来处理复杂的交互
- 将不同类型的交互分离到不同的中介者
- 使用组合模式组织多个中介者
3. 异常处理
- 在中介者中处理好异常情况
- 确保一个同事对象的异常不会影响其他对象
- 提供适当的错误恢复机制
4. 文档和监控
- 为中介者的交互协议提供清晰的文档
- 实现交互过程的监控和日志记录
- 考虑使用AOP来记录交互历史
总结 (Summary)
中介者模式是一种强大的行为型设计模式,它通过引入一个中介对象来封装一组对象之间的交互,从而降低了对象之间的耦合度。这种模式特别适合处理多个对象之间的复杂交互场景。
在实际应用中,中介者模式广泛应用于:
- GUI组件交互管理
- 聊天室和消息系统
- 事件驱动架构
- 工作流引擎
- 微服务通信协调
通过合理使用中介者模式,可以构建出松耦合、易维护的系统架构。然而,需要注意避免中介者变得过于复杂,以及避免单点故障问题。在设计时应该权衡好集中控制和分散逻辑之间的关系,确保系统的可扩展性和可维护性。
439



被折叠的 条评论
为什么被折叠?



