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);}
}
如果你覺得文章對你有幫助的話,請幫忙點點關注吧!謝謝啦