在实际的工作小组的交流过程是,组员向仲裁者报告,仲裁者向组员下达指示,组员之间不再互相询问和指示。Mediator模式是指,当发生麻烦事情的时候,通知仲裁者;当发生涉及全体组员的事情时,也通知仲裁者。当仲裁者下达指示时,组员会立即执行。团队组员之间不再互相沟通并私自做出决定,而是发生任何事情都向仲裁者报告。另一方面,仲裁者站在整个团队的角度上对组员上报的事情作出决定。

  示例程序是一个登录对话框,用户在其输入正确的用户名和密码后可以登录。

  对话框有以下一些要求:

  要调整多个对象之间的关系时,就需要用到Mediator模式了。即不让各个对象之间互相通信,而是增加一个仲裁者角色,让他们各自与仲裁者通信。然后,将控制显示的逻辑处理交给仲裁者。 

  

 public interface Mediator {
public abstract void createColleagues();
public abstract void colleagueChanged();
}

  Mediator接口是表示仲裁者的接口。createColleagues方法用于生成Mediator要管理的组员,即会生成对话框中的按钮和文本输入框等控件。colleagueChanged方法的作用是让组员可以向仲裁者进行报告,即当单选按钮和文本输入框的状态发生变化时,该方法会被调用。

 public interface Colleague {
public abstract void setMediator(Mediator mediator);
public abstract void setColleagueEnabled(boolean enabled);
}

  Colleague接口是表示向仲裁者进行报告的组员的接口。

  setMediator方法的作用是告知组员“我是仲裁者,有事情报告我”,向该方法中传递的参数是仲裁者的实例。之后在需要向仲裁者报告时(即调用colleagueChanged方法时),会调用该方法。

  setColleagueEnabled方法的作用是告知组员仲裁者所下达的指示。参数enabled为true,就表明自己需要变为“启用状态”,这也表明了状态并非由组员自己决定,而是由仲裁者来决定。

 import java.awt.Button;

 public class ColleagueButton extends Button implements Colleague {
private Mediator mediator; public ColleagueButton(String caption) {
super(caption);
} public void setMediator(Mediator mediator) { // 保存Mediator
this.mediator = mediator;
} public void setColleagueEnabled(boolean enabled) { // Mediator下达启用/禁用的指示
setEnabled(enabled);
}
}

  ColleagueButton类中mediator字段中保存了通过setMediator方法的参数传递进来的Mediator对象的实例。

  setColleagueEnabled方法会调用Button中的setEnabled方法,即setEnabled(true)后空间按钮可以被按下,否则无法被按下。

 import java.awt.TextField;
import java.awt.Color;
import java.awt.event.TextListener;
import java.awt.event.TextEvent; public class ColleagueTextField extends TextField implements TextListener, Colleague {
private Mediator mediator; public ColleagueTextField(String text, int columns) { // 构造函数
super(text, columns);
} public void setMediator(Mediator mediator) { // 保存Mediator
this.mediator = mediator;
} public void setColleagueEnabled(boolean enabled) { // Mediator下达启用/禁用的指示
setEnabled(enabled);
setBackground(enabled ? Color.white : Color.lightGray);
} public void textValueChanged(TextEvent e) { // 当文字发生变化时通知Mediator
mediator.colleagueChanged();
}
}

  ColleagueTextField类中textValueChanged方法是当捕捉到文本内容发生变化这一事情,就会通知给仲裁者。简单来说,当文本内容发生变化时,向仲裁者表达“对不起,文本内容有变化,请处理。”的意思。

  setColleagueEnabled方法中,不仅调用setEnabled方法,还调用setBackground方法来使控件启用后背景改成白色。

 import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent; public class ColleagueCheckbox extends Checkbox implements ItemListener, Colleague {
private Mediator mediator; public ColleagueCheckbox(String caption, CheckboxGroup group, boolean state) { // 构造函数
super(caption, group, state);
} public void setMediator(Mediator mediator) { // 保存Mediator
this.mediator = mediator;
} public void setColleagueEnabled(boolean enabled) { // Mediator下达启用/禁用指示
setEnabled(enabled);
} public void itemStateChanged(ItemEvent e) { // 当状态发生变化时通知Mediator
mediator.colleagueChanged();
}
}

  ColleagueCheckbox类是表示单选按钮的,同样可以通过itemStateChanged方法来捕捉单选按钮的状态变化。

 import java.awt.Frame;
import java.awt.Label;
import java.awt.Color;
import java.awt.CheckboxGroup;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent; public class LoginFrame extends Frame implements ActionListener, Mediator {
private ColleagueCheckbox checkGuest;
private ColleagueCheckbox checkLogin;
private ColleagueTextField textUser;
private ColleagueTextField textPass;
private ColleagueButton buttonOk;
private ColleagueButton buttonCancel; // 构造函数。
// 生成并配置各个Colleague后,显示对话框。
public LoginFrame(String title) {
super(title);
setBackground(Color.lightGray);
// 使用布局管理器生成4×2窗格
setLayout(new GridLayout(4, 2));
// 生成各个Colleague
createColleagues();
// 配置
add(checkGuest);
add(checkLogin);
add(new Label("Username:"));
add(textUser);
add(new Label("Password:"));
add(textPass);
add(buttonOk);
add(buttonCancel);
// 设置初始的启用起用/禁用状态
colleagueChanged();
// 显示
pack();
show();
} // 生成各个Colleague。
public void createColleagues() {
// 生成
CheckboxGroup g = new CheckboxGroup();
checkGuest = new ColleagueCheckbox("Guest", g, true);
checkLogin = new ColleagueCheckbox("Login", g, false);
textUser = new ColleagueTextField("", 10);
textPass = new ColleagueTextField("", 10);
textPass.setEchoChar('*');
buttonOk = new ColleagueButton("OK");
buttonCancel = new ColleagueButton("Cancel");
// 设置Mediator,事先告诉这些组员“我是仲裁者,有什么问题的可以像我报告。”
checkGuest.setMediator(this);
checkLogin.setMediator(this);
textUser.setMediator(this);
textPass.setMediator(this);
buttonOk.setMediator(this);
buttonCancel.setMediator(this);
// 设置Listener
checkGuest.addItemListener(checkGuest);
checkLogin.addItemListener(checkLogin);
textUser.addTextListener(textUser);
textPass.addTextListener(textPass);
buttonOk.addActionListener(this);
buttonCancel.addActionListener(this);
} // 接收来自于Colleage的通知然后判断各Colleage的启用/禁用状态。
public void colleagueChanged() {
if (checkGuest.getState()) { // Guest mode
textUser.setColleagueEnabled(false);
textPass.setColleagueEnabled(false);
buttonOk.setColleagueEnabled(true);
} else { // Login mode
textUser.setColleagueEnabled(true);
userpassChanged();
}
}

// 当textUser或是textPass文本输入框中的文字发生变化时
// 判断各Colleage的启用/禁用状态
private void userpassChanged() {
if (textUser.getText().length() > 0) {
textPass.setColleagueEnabled(true);
if (textPass.getText().length() > 0) {
buttonOk.setColleagueEnabled(true);
} else {
buttonOk.setColleagueEnabled(false);
}
} else {
textPass.setColleagueEnabled(false);
buttonOk.setColleagueEnabled(false);
}
} public void actionPerformed(ActionEvent e) {
System.out.println(e.toString());
System.exit(0);
}
}

  colleagueChanged作为最重要的方法,首先判断单选按钮状态,如果是游客模式,那么就禁用用户名输入框和密码输入框,同时使OK按钮开启。否则就是登录模式,这里和之前提到的逻辑一致。虽然三个组员类中都有设置自身的启用/禁用状态的方法,但是并没有“具体什么情况下需要设置哪种状态”的逻辑处理。他们都只是简单地调用仲裁者的colleagueChanged方法告知仲裁者“剩下的就拜托给你了”。也就是说,所有最终的决定都是由仲裁者的colleagueChanged方法下达的。

 import java.awt.*;
import java.awt.event.*; public class Main {
static public void main(String args[]) {
new LoginFrame("Mediator Sample");
}
}

  Main方法生成了LoginFrame类的实例。虽然Main类的main方法结束了,但是LoginFrame类的实例还一直被保存在AWT框架中。

  

最新文章

  1. Oracle Segments可以跨多个data files吗?
  2. hdu----(4686)Arc of Dream(矩阵快速幂)
  3. 基于Bootstrap的超酷jQuery开关按钮插件
  4. 《APUE》第四章笔记(1)
  5. 用Ajax调用web api,解决URL太长的问题;
  6. 开源消息总线ActiveMQ
  7. 用WebBrowser实现HTML界面的应用和交互 good
  8. [置顶] perl脚本中defined,exists和delete关键字的用法和区别
  9. 蓝牙Profile的概念和常见种类
  10. MongoDB安装(windows 10环境)
  11. eclipse使用jrebel
  12. SecureCRT安装
  13. Scala编程入门---Map与Tuple
  14. .NET Core 实践二:事件通知和异步处理
  15. axios简单理解
  16. ES6 js中const,var,let区别 今天第一次遇到const定义的变量
  17. (4.1)mysql备份还原——mysql常见故障
  18. UVa 1601 万圣节后的早晨
  19. 服务端tomcat的简单监控
  20. druid数据源

热门文章

  1. 4款黑科技级别的宝藏APP,能够轻松满足你的多种需求,请低调收藏
  2. Java后台开发方向面试题集合
  3. 快学Scala 第十三课 (类型层级,对象相等性)
  4. Spark 学习笔记之 Spark history Server 搭建
  5. Spark 学习笔记之 MONGODB SPARK CONNECTOR 插入性能测试
  6. 鱼和熊掌可兼得?一文看懂又拍云 SCDN
  7. 基于bootstrap 在同一个界面弹出不同的模态框
  8. logback颜色
  9. Feign【文件上传】
  10. 使用低版本的VS打开高版本项目的解决方案(以VS2008打开VS2010开发的项目为例)