中介者模式:解耦对象间复杂交互的设计模式
一、模式核心:用中介者统一管理对象交互,避免两两直接依赖
当系统中多个对象之间存在复杂的网状交互时(如 GUI 界面中按钮、文本框、下拉框的联动),对象间直接调用会导致关系混乱、难以维护。
中介者模式(Mediator Pattern) 通过引入一个中介者对象(Mediator),将对象间的直接交互转换为与中介者的单向交互。所有对象只需与中介者通信,由中介者协调处理交互逻辑,从而实现对象间的松耦合。核心解决:
- 交互复杂性:避免对象间形成复杂的依赖网络,降低系统复杂度。
- 可维护性:交互逻辑集中在中介者中,修改时只需调整中介者,无需修改多个对象。
- 扩展性:新增对象时只需实现与中介者的交互,不影响现有对象间的逻辑。
核心思想与 UML 类图
中介者模式包含以下角色:
- 中介者接口(Mediator):定义对象间交互的接口,如接收消息、分发消息。
- 具体中介者(Concrete Mediator):实现中介者接口,协调具体同事对象的交互。
- 同事类(Colleague):依赖中介者,通过中介者间接交互,不直接调用其他同事。

二、核心实现:GUI 界面组件的交互协调
1. 定义中介者接口
java
public interface Mediator {
void notify(Object sender, String event); // 接收消息(发送者、事件类型)
}
2. 实现具体中介者(处理组件联动)
java
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. 定义抽象同事类(组件基类)
java
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. 实现具体同事类(按钮、文本框、下拉框)
按钮组件
java
public class Button extends UIComponent {
public void onClick() {
System.out.println("按钮被点击");
sendEvent("click"); // 发送点击事件给中介者
}
}
文本框组件
java
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("文本框已清空");
}
}
下拉框组件
java
public class Dropdown extends UIComponent {
private String selectedItem;
public void setSelectedItem(String item) {
this.selectedItem = item;
System.out.println("下拉框选中:" + selectedItem);
}
}
5. 客户端初始化中介者与组件
java
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"); // 下拉框选择,通过中介者清空文本框
}
}
输出结果:
plaintext
按钮被点击
按钮点击:设置下拉框选项为 Option A
下拉框选中:Option A
模拟下拉框选择操作:
下拉框选择:清空文本框
文本框已清空
三、框架与源码中的中介者实践
1. Spring MVC 的 Controller 作为中介者
在 Spring MVC 中,Controller
作为中介者协调 Model
和 View
的交互:
View
(如 JSP)发送请求到Controller
。Controller
调用Model
处理业务逻辑,再将结果返回给View
。
java
@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
处理事件并协调组件状态更新。
java
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 系统改造 |
集中式逻辑管理 | 需要将交互逻辑集中管理与维护 | 工作流引擎、交易系统规则引擎 |
中介者模式通过 "中心化管理" 的设计,有效降低了对象间的耦合度,提升了系统的可维护性和扩展性。下一篇我们将探讨访问者模式,解析如何分离数据结构与操作,敬请期待!
扩展思考:中介者模式的缺点
- 中介者单点风险:中介者故障会导致整个系统交互失效,需通过冗余设计或分布式中介者缓解。
- 调试难度增加:交互逻辑集中在中介者中,需借助日志或调试工具追踪消息流程。