设计模式-中介模式
设计模式-中介者模式
中介者模式的英文翻译是 Mediator Design Pattern。它是这样定义的:Mediator pattern defines a separate (mediator) object that encapsulates the interaction between a set of objects and the objects delegate their interaction to a mediator object instead of interacting with each other directly. 翻译成中文就是:中介模式定义了一个单独的(中介)对象,来封装一组对象之间的交互。将这组对象之间的交互委派给与中介对象交互,来避免对象之间的直接交互。
避免对象之间的直接交互,如果了解观察者模式的话,它也避免了对象间的直接交互,观察者订阅关心的事件,在发生时进行自己的业务处理,如果观察者和被观察者之间使用消息队列,那更加没有直接交互了。

案例分析
举一个例子,Java 在很早之前其实是有图形化编程的,Java Swing,有一个 radio 单选,例如叫是否被表彰,如果选择是,则展示出两个组件,分别是 表彰等级,颁发单位,如果选择否,则取消这两个组件的展示并清空选项。
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemListener;
public class CommendationPanel extends JPanel {
private final JRadioButton rbYes = new JRadioButton("是");
private final JRadioButton rbNo = new JRadioButton("否");
private final JLabel lblLevel = new JLabel("表彰等级:");
private final JTextField txtLevel = new JTextField(15);
private final JLabel lblUnit = new JLabel("颁发单位:");
private final JTextField txtUnit = new JTextField(15);
public CommendationPanel() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.anchor = GridBagConstraints.WEST;
// --- 单选组 ---
ButtonGroup bg = new ButtonGroup();
bg.add(rbYes);
bg.add(rbNo);
gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2;
add(new JLabel("是否被表彰:"), gbc);
gbc.gridwidth = 1;
gbc.gridx = 0; gbc.gridy = 1;
add(rbYes, gbc);
gbc.gridx = 1;
add(rbNo, gbc);
// --- 受控组件 ---
gbc.gridx = 0; gbc.gridy = 2;
add(lblLevel, gbc);
gbc.gridx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1;
add(txtLevel, gbc);
gbc.gridx = 0; gbc.gridy = 3; gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0;
add(lblUnit, gbc);
gbc.gridx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1;
add(txtUnit, gbc);
// 初始状态
rbNo.setSelected(true);
toggleCommendationFields(false);
// 事件
ItemListener listener = e -> {
boolean selected = rbYes.isSelected();
toggleCommendationFields(selected);
if (!selected) { // 选“否”时清空
txtLevel.setText("");
txtUnit.setText("");
}
};
rbYes.addItemListener(listener);
rbNo.addItemListener(listener);
}
private void toggleCommendationFields(boolean visible) {
lblLevel.setVisible(visible);
txtLevel.setVisible(visible);
lblUnit.setVisible(visible);
txtUnit.setVisible(visible);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame("表彰信息");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new CommendationPanel());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
其中我们定义了单选框的点击事件并绑定到了选项上:
// 事件
ItemListener listener = e -> {
boolean selected = rbYes.isSelected();
toggleCommendationFields(selected);
if (!selected) { // 选“否”时清空
txtLevel.setText("");
txtUnit.setText("");
}
};
rbYes.addItemListener(listener);
rbNo.addItemListener(listener);
在点击事件中,我们会根据当前选项对其他组件的行为进行控制,即直接操作了其他对象。
中介者模式即我们定义一个操作类,所有的操作发送给中介(控制),由中介根据发送来的操作协调其他组件的行为。
例如又新增了 职称证书相关 的组件
import javax.swing.*;
import java.awt.event.ItemListener;
public class CommendationMediator {
/* ========== 表彰相关 ========== */
private final JRadioButton rbYes;
private final JRadioButton rbNo;
private final JLabel lblLevel;
private final JTextField txtLevel;
private final JLabel lblUnit;
private final JTextField txtUnit;
/* ========== 职称证书相关 ========== */
private final JRadioButton rbTitleYes;
private final JRadioButton rbTitleNo;
private final JLabel lblTitleLevel;
private final JTextField txtTitleLevel;
private final JLabel lblCertNo;
private final JTextField txtCertNo;
public CommendationMediator(JRadioButton rbYes,
JRadioButton rbNo,
JLabel lblLevel,
JTextField txtLevel,
JLabel lblUnit,
JTextField txtUnit,
JRadioButton rbTitleYes,
JRadioButton rbTitleNo,
JLabel lblTitleLevel,
JTextField txtTitleLevel,
JLabel lblCertNo,
JTextField txtCertNo) {
this.rbYes = rbYes;
this.rbNo = rbNo;
this.lblLevel = lblLevel;
this.txtLevel = txtLevel;
this.lblUnit = lblUnit;
this.txtUnit = txtUnit;
this.rbTitleYes = rbTitleYes;
this.rbTitleNo = rbTitleNo;
this.lblTitleLevel = lblTitleLevel;
this.txtTitleLevel = txtTitleLevel;
this.lblCertNo = lblCertNo;
this.txtCertNo = txtCertNo;
/* ---- 初始状态 ---- */
rbNo.setSelected(true);
rbTitleNo.setSelected(true);
toggleCommendationFields(false);
toggleTitleFields(false);
/* ---- 统一事件处理 ---- */
ItemListener commendationListener = e -> {
boolean yes = rbYes.isSelected();
toggleCommendationFields(yes);
if (!yes) {
txtLevel.setText("");
txtUnit.setText("");
}
};
rbYes.addItemListener(commendationListener);
rbNo.addItemListener(commendationListener);
ItemListener titleListener = e -> {
boolean yes = rbTitleYes.isSelected();
toggleTitleFields(yes);
if (!yes) {
txtTitleLevel.setText("");
txtCertNo.setText("");
}
};
rbTitleYes.addItemListener(titleListener);
rbTitleNo.addItemListener(titleListener);
}
private void toggleCommendationFields(boolean visible) {
lblLevel.setVisible(visible);
txtLevel.setVisible(visible);
lblUnit.setVisible(visible);
txtUnit.setVisible(visible);
}
private void toggleTitleFields(boolean visible) {
lblTitleLevel.setVisible(visible);
txtTitleLevel.setVisible(visible);
lblCertNo.setVisible(visible);
txtCertNo.setVisible(visible);
}
}
这样的好处是对象间的耦合减弱,大家都只需要和中介者交互,无需维护复杂的对象间关系,缺点则是所有的操作集中在 中介者 类中,时间长可能会生成大而全的 上帝 类(God Class)。
总结
中介模式在生活中的场景例如航空,每个飞机不需要知道其他飞机的飞行线路,只需要联系塔台,由塔台来负责每架飞机的航线调度。这样就大大简化了通信网络。
中介模式的设计思想跟中间层很像,通过引入中介这个中间层,将一组对象之间的交互关系(或者依赖关系)从多对多(网状关系)转换为一对多(星状关系)。原来一个对象要跟 n 个对象交互,现在只需要跟一个中介对象交互,从而最小化对象之间的交互关系,降低了代码的复杂度,提高了代码的可读性和可维护性。
中介模式和观察者模式都可以实现对象间的结果。不过在观察者模式中,(观察者)和(被观察者)的身份几乎固定,只有被观察者影响观察者的行为;但是在中介模式中,所有的对象既可以被影响,也可以影响其他对象,而且可以借助中介者先后调用不同参与者的方法来解决观察者模式中无法顺序控制的问题。
更多推荐

所有评论(0)