中介者模式:解耦對象間復雜交互的設計模式
一、模式核心:用中介者統一管理對象交互,避免兩兩直接依賴
當系統中多個對象之間存在復雜的網狀交互時(如 GUI 界面中按鈕、文本框、下拉框的聯動),對象間直接調用會導致關系混亂、難以維護。
中介者模式(Mediator Pattern) 通過引入一個中介者對象(Mediator),將對象間的直接交互轉換為與中介者的單向交互。所有對象只需與中介者通信,由中介者協調處理交互邏輯,從而實現對象間的松耦合。核心解決:
- 交互復雜性:避免對象間形成復雜的依賴網絡,降低系統復雜度。
- 可維護性:交互邏輯集中在中介者中,修改時只需調整中介者,無需修改多個對象。
- 擴展性:新增對象時只需實現與中介者的交互,不影響現有對象間的邏輯。
核心思想與 UML 類圖
中介者模式包含以下角色:
- 中介者接口(Mediator):定義對象間交互的接口,如接收消息、分發消息。
- 具體中介者(Concrete Mediator):實現中介者接口,協調具體同事對象的交互。
- 同事類(Colleague):依賴中介者,通過中介者間接交互,不直接調用其他同事。
二、核心實現:GUI 界面組件的交互協調
1. 定義中介者接口
public interface Mediator { void notify(Object sender, String event); // 接收消息(發送者、事件類型)
}
2. 實現具體中介者(處理組件聯動)
public class UIMediator implements Mediator { private Button button; private TextBox textBox; private Dropdown dropdown; // 設置中介者關聯的組件 public void setButton(Button button) { this.button = button; } public void setTextBox(TextBox textBox) { this.textBox = textBox; } public void setDropdown(Dropdown dropdown) { this.dropdown = dropdown; } @Override public void notify(Object sender, String event) { if (sender == button && "click".equals(event)) { // 按鈕點擊時,獲取文本框內容并更新下拉框 String text = textBox.getText(); dropdown.setSelectedItem(text); System.out.println("按鈕點擊:設置下拉框選項為 " + text); } else if (sender == dropdown && "select".equals(event)) { // 下拉框選擇時,清空文本框 textBox.clear(); System.out.println("下拉框選擇:清空文本框"); } }
}
3. 定義抽象同事類(組件基類)
public abstract class UIComponent { protected Mediator mediator; public void setMediator(Mediator mediator) { this.mediator = mediator; } protected void sendEvent(String event) { if (mediator != null) { mediator.notify(this, event); // 通過中介者發送事件 } }
}
4. 實現具體同事類(按鈕、文本框、下拉框)
按鈕組件
public class Button extends UIComponent { public void onClick() { System.out.println("按鈕被點擊"); sendEvent("click"); // 發送點擊事件給中介者 }
}
文本框組件
public class TextBox extends UIComponent { private String text; public String getText() { return text; } public void setText(String text) { this.text = text; } public void clear() { text = ""; System.out.println("文本框已清空"); }
}
下拉框組件
public class Dropdown extends UIComponent { private String selectedItem; public void setSelectedItem(String item) { this.selectedItem = item; System.out.println("下拉框選中:" + selectedItem); }
}
5. 客戶端初始化中介者與組件
public class ClientDemo { public static void main(String[] args) { // 創建中介者和組件 UIMediator mediator = new UIMediator(); Button button = new Button(); TextBox textBox = new TextBox(); Dropdown dropdown = new Dropdown(); // 組件關聯中介者 button.setMediator(mediator); textBox.setMediator(mediator); dropdown.setMediator(mediator); // 中介者關聯組件(雙向綁定) mediator.setButton(button); mediator.setTextBox(textBox); mediator.setDropdown(dropdown); // 模擬用戶操作:文本框輸入內容,按鈕點擊觸發聯動 textBox.setText("Option A"); button.onClick(); // 按鈕點擊,通過中介者更新下拉框 System.out.println("\n模擬下拉框選擇操作:"); mediator.notify(dropdown, "select"); // 下拉框選擇,通過中介者清空文本框 }
}
輸出結果:
按鈕被點擊
按鈕點擊:設置下拉框選項為 Option A
下拉框選中:Option A 模擬下拉框選擇操作:
下拉框選擇:清空文本框
文本框已清空
三、框架與源碼中的中介者實踐
1. Spring MVC 的 Controller 作為中介者
在 Spring MVC 中,Controller
作為中介者協調 Model
和 View
的交互:
View
(如 JSP)發送請求到Controller
。Controller
調用Model
處理業務邏輯,再將結果返回給View
。
@Controller
public class UserController { @Autowired private UserService userService; // Model 層 @GetMapping("/user/{id}") public String getUser(@PathVariable int id, Model model) { User user = userService.getUser(id); model.addAttribute("user", user); // 中介者傳遞數據到 View return "user.jsp"; // 中介者決定返回視圖 }
}
2. Android 的 Activity 作為中介者
Android 中 Activity
作為中介者管理界面組件(Button
、EditText
等)的交互:
- 組件通過
setOnClickListener
注冊事件到Activity
。 Activity
處理事件并協調組件狀態更新。
public class MainActivity extends AppCompatActivity { private EditText editText; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = findViewById(R.id.edit_text); textView = findViewById(R.id.text_view); findViewById(R.id.button).setOnClickListener(v -> { String text = editText.getText().toString(); textView.setText("輸入內容:" + text); // 中介者協調組件交互 }); }
}
3. Java Swing 的 Event Dispatch Thread
Swing 通過事件分發線程(中介者)處理組件事件,避免組件間直接通信:
- 按鈕點擊事件由
Event Dispatch Thread
接收并分發給注冊的監聽器。
四、避坑指南:正確使用中介者模式的 3 個要點
1. 避免中介者過度復雜
若中介者承擔過多職責,會形成 “上帝對象”。可將中介者拆分為多個專用中介者(如訂單中介者、支付中介者),或引入分層結構(如中介者 + 協調者)。
2. 平衡中介者與同事的職責
同事類應盡量保持簡單,僅包含自身狀態和基本操作,復雜邏輯集中在中介者中。若同事類需要頻繁調用中介者,需檢查是否違反單一職責原則。
3. 區分中介者模式與觀察者模式
- 中介者模式:對象間通過中介者間接交互,形成星型結構(非廣播式)。
- 觀察者模式:主題與觀察者是一對多的依賴關系,觀察者被動接收通知(廣播式)。
六、總結:何時該用中介者模式?
適用場景 | 核心特征 | 典型案例 |
---|---|---|
對象間網狀交互 | 多個對象間存在復雜直接調用 | GUI 界面組件聯動、分布式系統節點通信 |
系統重構解耦 | 遺留系統中對象間緊耦合,需簡化依賴 | 微服務間消息路由、legacy 系統改造 |
集中式邏輯管理 | 需要將交互邏輯集中管理與維護 | 工作流引擎、交易系統規則引擎 |
中介者模式通過 “中心化管理” 的設計,有效降低了對象間的耦合度,提升了系統的可維護性和擴展性。下一篇我們將探討訪問者模式,解析如何分離數據結構與操作,敬請期待!
擴展思考:中介者模式的缺點
- 中介者單點風險:中介者故障會導致整個系統交互失效,需通過冗余設計或分布式中介者緩解。
- 調試難度增加:交互邏輯集中在中介者中,需借助日志或調試工具追蹤消息流程。