Author:Gorit
Date:2021年11月21日
Refer:《图解设计模式》
Website:CodingGorit 的小站

16.1 Mediator 模式

“Mediator”意思指的是 “仲裁者”、“中介者”

一方面,当发生麻烦事情的时候,通知仲裁者
另一方面,当发生涉及全体组员的事情时,也通知仲裁者。

当仲裁者下达指示时,组员立刻执行。团队组员之间不再互相沟通并私自做出决定,而是发生任何事情都要向仲裁者汇报。

另外仲裁者站在整个团队的角度上对组员上报的事情做出决定,这就是 Mediator 模式。

16.2 示例程序

类名 说明
Mediator 定义“仲裁者”的接口(API)
Colleague 定义“组员”的接口(API)
ColleagueButton 表示按钮的类,它实现了 Colleague 接口
ColleagueTextField 表示文本输入框的类。它实现了 Colleague 接口
ColleagueRadioBox 表示勾选框(单选框),实现 Colleague 接口
LoginFrame 表示登录对话框的类
Main 测试程序行为的类

Mediator接口

  1. package Mediator;
  2. /**
  3. * @Author Gorit
  4. * @Date 2021/11/21
  5. * 仲裁者接口
  6. **/
  7. public interface Mediator {
  8. public abstract void createColleagues(); // 生成 Mediator 要管理的成员
  9. public abstract void colleagueChanged(); // 该方法会被各个 Colleague 组员调用。它的作用是让组员可以向仲裁者汇报
  10. }

Colleague 接口

  1. package Mediator;
  2. /**
  3. * @Author Gorit
  4. * @Date 2021/11/21
  5. * 仲裁者接口
  6. **/
  7. public interface Mediator {
  8. public abstract void createColleagues(); // 生成 Mediator 要管理的成员
  9. public abstract void colleagueChanged(); // 该方法会被各个 Colleague 组员调用。它的作用是让组员可以向仲裁者汇报
  10. }

ColleagueButton

  1. package Mediator;
  2. import java.awt.*;
  3. /**
  4. * @Author Gorit
  5. * @Date 2021/11/21
  6. * 与 LoginFrame 协作
  7. **/
  8. public class ColleagueButton extends Button implements Colleague {
  9. private Mediator mediator;
  10. public ColleagueButton(String caption) {
  11. super(caption);
  12. }
  13. public void setMediator(Mediator mediator) { // 保存 Mediator
  14. this.mediator = mediator;
  15. }
  16. public void setColleagueEnabled(boolean enabled) { // Mediator 下达启用, 禁用指示
  17. setEnabled(enabled);
  18. }
  19. }

ColleagueTextField

  1. package Mediator;
  2. import java.awt.*;
  3. import java.awt.event.TextEvent;
  4. import java.awt.event.TextListener;
  5. /**
  6. * @Author Gorit
  7. * @Date 2021/11/21
  8. **/
  9. public class ColleagueTextField extends TextField implements TextListener, Colleague {
  10. private Mediator mediator;
  11. public ColleagueTextField(String text, int columns) { // 构造函数
  12. super(text, columns);
  13. }
  14. public void setMediator(Mediator mediator) {
  15. this.mediator = mediator;
  16. }
  17. public void setColleagueEnabled(boolean enabled) { // Mediator 下达启用,禁用指令
  18. setEnabled(enabled);
  19. setBackground(enabled ? Color.WHITE : Color.LIGHT_GRAY);
  20. }
  21. public void textValueChanged(TextEvent e) { // 当文字发生变化时,通知 Mediator
  22. mediator.colleagueChanged();
  23. }
  24. }

ColleagueRadioBox

  1. package Mediator;
  2. import java.awt.*;
  3. import java.awt.event.ItemEvent;
  4. import java.awt.event.ItemListener;
  5. /**
  6. * @Author Gorit
  7. * @Date 2021/11/21
  8. **/
  9. public class ColleagueRadioBox extends Checkbox implements ItemListener,Colleague {
  10. private Mediator mediator;
  11. public ColleagueRadioBox(String label, CheckboxGroup group, boolean state) {
  12. super(label, group, state);
  13. }
  14. public void setMediator(Mediator mediator) {
  15. this.mediator = mediator;
  16. }
  17. public void setColleagueEnabled(boolean enabled) {
  18. setEnabled(enabled);
  19. }
  20. public void itemStateChanged(ItemEvent e) {
  21. mediator.colleagueChanged();
  22. }
  23. }

LoginFrame

  1. package Mediator;
  2. import java.awt.*;
  3. import java.awt.event.ActionEvent;
  4. import java.awt.event.ActionListener;
  5. /**
  6. * @Author Gorit
  7. * @Date 2021/11/21
  8. * 仲裁者代码
  9. **/
  10. public class LoginFrame extends Frame implements ActionListener, Mediator {
  11. private ColleagueRadioBox checkGuest;
  12. private ColleagueRadioBox checkLogin;
  13. private ColleagueTextField textUser;
  14. private ColleagueTextField textPass;
  15. private ColleagueButton buttonOk;
  16. private ColleagueButton buttonCancel;
  17. /**
  18. * 设置背景色
  19. * 设置布局管理器 (4行 2列)
  20. * 调用 createColleagues 方法生成 Colleagues
  21. * 设置 Colleague
  22. * 设置初始状态
  23. * 显示
  24. * @param title
  25. */
  26. public LoginFrame(String title) {
  27. super(title);
  28. setBackground(Color.lightGray);
  29. // 使用布局管理器生成 4x2的窗格
  30. setLayout(new GridLayout(4, 2));
  31. // 生成各个 Colleague
  32. createColleagues();
  33. // 配置
  34. add(checkGuest);
  35. add(checkLogin);
  36. add(new Label("Username:"));
  37. add(textUser);
  38. add(new Label("Password:"));
  39. add(textPass);
  40. add(buttonOk);
  41. add(buttonCancel);
  42. // 设置初始化应用 禁用状态
  43. colleagueChanged();
  44. // 显示
  45. pack();
  46. show();
  47. }
  48. // 生成各个 Colleague
  49. public void createColleagues() {
  50. // 生成
  51. CheckboxGroup q = new CheckboxGroup();
  52. checkGuest = new ColleagueRadioBox("Guest", q, true);
  53. checkLogin = new ColleagueRadioBox("Login", q, false);
  54. textUser = new ColleagueTextField("", 16);
  55. textPass = new ColleagueTextField("", 16);
  56. textPass.setEchoChar('*');
  57. buttonOk = new ColleagueButton("OK");
  58. buttonCancel = new ColleagueButton("Cancel");
  59. // 设置 Mediator
  60. checkGuest.setMediator(this);
  61. checkLogin.setMediator(this);
  62. textUser.setMediator(this);
  63. textPass.setMediator(this);
  64. buttonOk.setMediator(this);
  65. buttonCancel.setMediator(this);
  66. // 设置 Listener
  67. checkGuest.addItemListener(checkGuest);
  68. checkLogin.addItemListener(checkLogin);
  69. textUser.addTextListener(textUser);
  70. textPass.addTextListener(textPass);
  71. buttonOk.addActionListener(this);
  72. buttonCancel.addActionListener(this);
  73. }
  74. // 接收来自 Colleague 的通知然后判断各 Colleague 的启用 / 禁用。 简单的登录框逻辑转换
  75. public void colleagueChanged() {
  76. if (checkGuest.getState()) { // Guest mode
  77. textUser.setColleagueEnabled(false);
  78. textPass.setColleagueEnabled(false);
  79. buttonOk.setColleagueEnabled(true);
  80. } else { // Login mode
  81. textUser.setColleagueEnabled(true);
  82. userpassChanged();
  83. }
  84. }
  85. // 当 textUser 或 textPass 文本输入框中的文字发生变化时
  86. // 判断各 Colleague 的启用 | 禁用
  87. private void userpassChanged() {
  88. if (textUser.getText().length() > 0) {
  89. textPass.setColleagueEnabled(true);
  90. if (textPass.getText().length() > 0) {
  91. buttonOk.setColleagueEnabled(true);
  92. } else {
  93. buttonOk.setColleagueEnabled(false);
  94. }
  95. } else {
  96. textPass.setColleagueEnabled(false);
  97. buttonOk.setColleagueEnabled(false);
  98. }
  99. }
  100. public void actionPerformed(ActionEvent e) {
  101. System.out.println(e.toString());
  102. System.exit(0);
  103. }
  104. }

Main

  1. package Mediator;
  2. /**
  3. * @Author Gorit
  4. * @Date 2021/11/21
  5. **/
  6. public class Main {
  7. static public void main(String[] args) {
  8. new LoginFrame("Mediator Sample");
  9. }
  10. }

16.3 Mediator 模式中登场的角色

一、Mediator(仲裁者、中介者)

Mediator 角色负责定义与 Colleague 角色进行通信和做出决定的接口(API)。在示例程序中,由 Mediator 接口扮演此角色。

二、ConcreateMediator(具体的仲裁者,中介者)

ConcreateMediator 负责实现 Mediator 接口,示例程序中由 LoginFrame 扮演此角色。

三、Colleague 同事

Colleague 角色负责定义与 Mediator 角色进行通信的接口(API),示例程序中由 Colleague接口担任此角色

四、ConcreateColleague

ColleagueButton、ColleagueRadioBox、ColleagueTextField 扮演此角色。

16.4 相关设计模式

一、Facade 模式

在 Mediator 模式中,Mediator 角色与 Colleague 角色进行交互
因此说 Mediator 是双向的,Facade 角色单方面的使用其他角色提供的接口(API),因此是单向的

二、Observer 模式

有时会使用 Observer 模式来实现,Mediator 和 Colleague 角色进行通信