》》组员向仲裁者报告,仲裁者向组员下达指示。组员之间不再相互
询问和相互指示。
》》在该模式中:一方面,当发生麻烦事情的时候,通知仲裁者;当
发生涉及全体组员的事情时,也通知仲裁者。当仲裁者下达指示时,
组员会立即执行。团队组员之间不再互相沟通并私自做出决定,而
是发生任何事情都向仲裁者报告。另一方面,仲裁者站在整个团队
的角度对组员上报的事情做出决定。
------------------下面的示例程序是一个GUI 应用程序,它展示了一个登
陆对话框,用户在其中输入正确的用户名和密码后可以登陆。
》》要调整多个对象之间的关系时,就需要用到 Mediator 模式了。
即不让各个对象之间互相通信,而是增加一个仲裁者角色,让
他们各自与仲裁者通信。然后,将控制显式的逻辑处理交给仲
裁者负责。
》》登陆对话框:
对话框的使用方法如下:
*** 可以选择作为游客访问(Guest) 或是作为用户登陆(Login)
*** 作为用户登陆时,需要输入正确的用户名(Username)和密码(Password)
*** 点击OK按钮可以登陆,点击 Cancel 按钮可以取消登陆
(在示例程序中我们不会真正登陆,而是在按下按钮后就退出程序)
具体的要求:
*** 如果选择作为游客访问,那么禁用用户名输入框和密码输入框,使用户无法输入
*** 如果选择作为用户登陆,那么启用用户名输入和密码输入框,使用户可以输入
*** 如果在用户名输入框中一个字符都没有输入,那么禁用密码输入框,使用户无法
输入密码
*** 如果用户名输入框中输入至少一个字符,那么启用密码输入框,使用户可以输入
密码(当然,如果选择作为游客访问,那么密码框依然是禁用状态)
*** 只有当用户名输入框和密码输入框中都至少输入一个字符后,OK 按钮才处于启
用状态,可以被按下。用户名输入框或密码输入框中一个字符都没有被输入的时
候,禁用 OK 按钮,使其不可被按下(当然,如果选择作为游客访问,那么OK
按钮总是处于启用状态)
*** Cancel 按钮总是处于启用状态,任何时候都可以按下该按钮。
-----------------------------------------
《示例程序的类图》
》》Mediator 接口:
package mediator;
/*
* 该接口是表示仲裁者的接口
*/
public interface Mediator {
/*
* 生成 Mediator 要管理的组员,在示例程序中,createColleagues()
* 会生成对话框中的按钮和文本输入框等控件
*/
public abstract void createColleagues();
/*
* colleagueChanged()该方法会被各个 Colleague 组员调用。
* 它的作用是让组员可以向仲裁者进行报告。在本例 中,当单选按钮和文本
* 输入框的状态发生变化时,该方法会被调用。
*/
public abstract void colleagueChanged();
}
》》Colleague 接口:
package mediator;
/*
* 该接口表示的是向仲裁者进行报告的组员的接口
*/
public interface Colleague {
/*
* 该方法的作用是告知组员“我是仲裁者,有事请报告我”。向该方法中传递的参数是
* 仲裁者的实例,之后在需要向仲裁者报告时(即调用colleagueChanged() )
* 会用到该实例
*/
public abstract void setMediator(Mediator mediator);
/*
* 该方法的作用是告知组员仲裁者所下达的指示。参数 enabled 如果为 true ,
* 就表示自己需要变为“启动状态”;如果是 false ,则表示自己需要变为
* “禁止状态”。这个方法表明,究竟是变为“启动状态”还是变为“禁止状态”,
* 并非由组员自己决定,而是由仲裁者来决定。
*/
public abstract void setColleagueEnabled(boolean enabled);
}
》》ColleagueButton 类:
package mediator;
import java.awt.Button;
/*
* 按钮
*/
public class ColleagueButton extends Button implements Colleague {
private Mediator mediator;
//给该按钮指定标签
public ColleagueButton(String string){
super(string);
}
//保存该按钮的仲裁者
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
//Mediator 下达启用/禁止的指示
public void setColleagueEnabled(boolean enabled) {
setEnabled(enabled);
}
}
》》ColleagueTextField 类:
package mediator;
import java.awt.Color;
import java.awt.TextField;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
public class ColleagueTextField extends TextField implements Colleague,TextListener {
private Mediator mediator;
//单行文本初始化(使用构造函数 )
public ColleagueTextField(String string , int columns){
super(string , columns);
}
//保存该单行文本的仲裁者
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
//Mediator 下达启用/禁用的指示
public void setColleagueEnabled(boolean enabled) {
setEnabled(enabled);
//当启用时,文本框的背景是白色;当禁用时,文本框的背景是灰色
setBackground(enabled? Color.white:Color.lightGray);
}
/*
* java.awt.event.TextListener 接口里面的方法
* 当文字发生变化时 通知 仲裁者 Mediator
*
* 当文本内容发生变化时,AWT 框架会调用该方法
*/
public void textValueChanged(TextEvent e){
mediator.colleagueChanged();
}
}
》》ColleagueCheckbox 类:
package mediator;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
public class ColleagueCheckbox extends Checkbox implements ItemListener,Colleague {
private Mediator mediator;
//复选按钮的构造函数,CheckboxGroup 类用于集合 Checkbox 按钮集。
public ColleagueCheckbox(String caption , CheckboxGroup group , boolean state){
super(caption , group , state);
}
//设置该复选框的仲裁者
public void setMediator(Mediator mediator){
this.mediator = mediator;
}
//Meidator 下达启用/禁用指示
public void setColleagueEnabled(boolean enabled){
setEnabled(enabled);
}
/*
* java.awt.event.ItemListener 接口中的方法
* 在用户已选定或取消选定某项时调用。
*/
public void itemStateChanged(ItemEvent e) {
mediator.colleagueChanged();
}
}
》》 LoginFrame 类:
package mediator;
import java.awt.CheckboxGroup;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
public class LoginFrame extends Frame implements ActionListener, Mediator,
WindowListener{
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.LIGHT_GRAY);
//使用布局管理器生成 4*2 窗格
setLayout(new GridLayout(4,2));
//给该窗口增加一个窗口监听器
this.addWindowListener(this);
//生成各个 Colleague
createColleagues();
//配置
add(checkGuest);
add(checkLogin);
add(new Label("Username:"));
add(textUser);
add(new Label("Password"));
add(textPass);
add(buttonOk);
add(buttonCancel);
//设置初始的启用、禁用状态
colleagueChanged();
//显示
pack();
setVisible(true);
}
//生成各个 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);
}
//接收来自于 Colleague 的通知然后判断各 Colleague 的启用/禁用状态
public void colleagueChanged() {
/*
*当 Guest 按钮是开着的,那用户名和密码框就是关闭的,而ok 按钮是开着的
*/
//Guest 模式
if(checkGuest.getState()){
textUser.setColleagueEnabled(false);
textPass.setColleagueEnabled(false);
buttonOk.setColleagueEnabled(true);
}else{
//Login 模式
textUser.setColleagueEnabled(true);
userpassChanged();
}
}
/*
* 当 textUser 或 textPass 文本输入框中的文字发生变化时,
* 判断各 Colleague 的启用 / 禁用状态
*/
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);
}
}
/*
* java.awt.event.ActionListener 接口
* 里面的方法
*/
public void actionPerformed(ActionEvent e) {
System.out.println(e.toString());
System.exit(0);
}
//java.awt.event.WindowListener 接口中的方法
@Override
public void windowOpened(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
@Override
public void windowClosed(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowIconified(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowDeiconified(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowActivated(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowDeactivated(WindowEvent e) {
// TODO Auto-generated method stub
}
}
》》Main 类-----》测试程序
package mediator;
public class Main {
public static void main(String[] args){
new LoginFrame("Mediator Sample");
}
}
-----------------------------------------------
《Mediator 模式中的登场角色》
**** Mediator (仲裁者、中介者)
Mediator 角色负责定义与 Colleague 角色进行通信和做出决定的接口。
在示例程序中,由 Mediator 接口扮演此角色。
**** ConcreteMediator (具体的仲裁者、中介者)
ConcreteMediator 角色负责实现 Mediator 角色的接口,负责实际做出
决定。在示例程序中,由 LoginFrame 类扮演此角色。
**** Colleague (同事)
Colleague 角色负责定义与 Mediator 角色进行通信的接口。在示例程序
中,由 Colleague 接口扮演此角色。
**** ConcreteColleague (具体的同事)
ConcreteColleague 角色负责定义实现 Colleague 角色的接口。在示例
程序中,由 ColleagueButton 类、ColleagueTextField 类 和
ColleagueCheckbox 类扮演此角色。
-----------------------------------------------
《扩展思路要点》
1.当发生分散灾难时
2.通信线路的增加
3.哪些角色可以复用
上面的示例程序中的 ConcreteColleague 角色可以复用,但是
ConcreteMediator 角色很难复用。
------------------------------------------------
《相关的设计模式》
**** Facade 模式
**** Observer 模式