整个团队的交流过程如果变成了为了组员向仲裁者报告,仲裁者向组员下达指令。组员之间不再相互询问和互相指示。Mediator的意思就是“仲裁者”、“中介者”。一方面,当发生麻烦事情的时候,通知仲裁者;当发生涉及全体组员的事情的时候,也通知仲裁者。当仲裁者下达指令时,组员会立即执行。团队组员之间不再相互沟通并私自做出决定,而是发生任何事情都向仲裁者报告。另一方面,仲裁者站在整个团队的角度上对组员上报的事情做出决定。这就是Mediator模式。
示例程序:
对于一个简单的登录对话框,使用方法如下:
- 可以选择作为作为游客登录或作为用户登录。
- 作为用户登录时,需要输入正确的用户名和密码。
- 点击ok按钮可以登录,点击Cancel按钮可以取消登录
但其实里面的逻辑还是比较复杂的:
- 如果选择作为游客访问,那么禁用用户名输入框和密码输入框,使用户无法输入。
- 如果选择走位用户访问,那么启用用户名输入框和密码输入框,使用户可以输入。
- 如果在用户名输入框中一个字符都没有输入,那么禁用密码输入框,使用户无法输入密码。
- 如果在用户名输入框中输入了至少一个字符,那么启用密码输入框,使用户可以输入密码。
- 只有当用户名输入框和密码输入框中都至少输入一个字符后,ok按钮才处于启动状态,可以被按下。用户名输入框或密码输入框中一个字符都没有被输入的时候,禁用ok按钮,使其不可被按下。
- Cancel按钮总是处于启用状态,任何时候都可以按下该按钮。
对话框中的单选按钮、文本输入框、确认或者取消按钮都是单独的类。如果将上面的逻辑处理分散在个各类中,那么编码的工作量会变得非常大。这是因为所有的对象都是相互制约、相互关联的。
类和接口的一览表:
| 名字 | 说明 |
|---|---|
| Mediator | 定义“仲裁者”的接口(API)的接口 |
| Colleague | 定义“组员”的接口(API)的接口 |
| ColleagueButton | 表现按钮的类。它实现了Colleague接口 |
| ColleagueTextField | 表示文本输入框的类。它实现了Colleague接口 |
| ColleagueCheckbox | 表示勾选框的类,它实现了Colleague接口 |
| LoginFrame | 表示登录对话框的类,它实现了Mediator接口 |
| Maiin | 测试程序行为的类 |
Mediator接口:
public interface Mediator {public abstract void creatColleague(); // 用于生成对话框的按钮和文本输入框等控件public abstract void colleagueChanged(); // 会被各个Colleague组员调用。它的作用是让组员可以向仲裁者进行报告}
Colleague接口:
是表示向仲裁者进行报告的组员安的接口。具体的组员会实现这个接口。
public interface Colleague {public abstract void setMediator(Mediator mediator); // 告知组员我是仲裁者,向该方法中传递的参数是仲裁者的实例对象public abstract void setColleagueEnabled(boolean enabled); // 告诉组员仲裁者下达的指示。// 参数enabled如果为true,就表示为自己需要变为"启动状态",这个方法表明,到底是启用还是禁用,并非// 由组员自己决定,而是由仲裁者决定}
ColleagueButton类:
控制按钮的启用/关闭状态。
public class ColleagueButton extends Button implements Colleague {private Mediator mediator;public ColleagueButton(String caption) {super(caption);}@Overridepublic void setMediator(Mediator mediator) { // 保存Mediatorthis.mediator = mediator;}@Overridepublic void setColleagueEnabled(boolean enabled) { // Mediator下达启用/禁用的命令setEnabled(enabled);}}
ColleagueTextField:
public class ColleagueTextField extends TextField implements TextListener,Colleague {private Mediator mediator;public ColleagueTextField(String text,int columns){super(text,columns);}@Overridepublic void setMediator(Mediator mediator) {this.mediator = mediator;}@Overridepublic void setColleagueEnabled(boolean enabled) {setEnabled(true);setBackground(enabled ? Color.white : Color.lightGray);}@Overridepublic void textValueChanged(TextEvent e) {mediator.colleagueChanged(); // 当文字发生变化时通知Mediator}}
ColleagueCheckbox类:
public class ColleagueCheckbox extends Checkbox implements ItemListener,Colleague {private Mediator mediator;public ColleagueCheckbox(String label, boolean state, CheckboxGroup group) throws HeadlessException {super(label, state, group); // 构造函数}@Overridepublic void setMediator(Mediator mediator) { // 保存mediatorthis.mediator = mediator;}@Overridepublic void setColleagueEnabled(boolean enabled) { // mediator下达启用/ 禁用指示setEnabled(enabled);}@Overridepublic void itemStateChanged(ItemEvent e) {mediator.colleagueChanged(); // 当状态发生变化时通知mediator}}
LoginFrame:
最终所有的决定都是由仲裁者的colleagueChanged下达的。
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));// 生成各个ColleaguecreatColleague();// 配置add(checkGuest);add(checkLogin);add(new Label("Username:"));add(textUser);add(new Label("Password:"));add(textPass);add(buttonOk);add(buttonCancel);// 设置初始的启用 / 禁用状态colleagueChanged();// 显示pack();show();}// 生成各个Colleague@Overridepublic void creatColleague() {// 生成CheckboxGroup g = new CheckboxGroup();checkGuest = new ColleagueCheckbox("Guest", true, g);checkLogin = new ColleagueCheckbox("Login", false, g);textUser = new ColleagueTextField("", 10);textPass = new ColleagueTextField("", 10);textPass.setEchoChar('*');buttonOk = new ColleagueButton("OK");buttonCancel = new ColleagueButton("Cancel");// 设置MediatorcheckGuest.setMediator(this);checkLogin.setMediator(this);textUser.setMediator(this);textPass.setMediator(this);buttonOk.setMediator(this);buttonCancel.setMediator(this);// 设置ListenercheckGuest.addItemListener(checkGuest);checkLogin.addItemListener(checkLogin);textUser.addTextListener(textUser);textPass.addTextListener(textPass);buttonOk.addActionListener(this);buttonCancel.addActionListener(this);}// 接收来自于colleague的通知然后判断各Colleague的启用/禁用状态@Overridepublic void colleagueChanged() {if (checkGuest.getState()) {textUser.setColleagueEnabled(false);textPass.setColleagueEnabled(false);buttonOk.setEnabled(true);} else {textUser.setColleagueEnabled(true);}}// 当textUser或textPass文本输入框中的文字发生变化时// 判断各College的启用 / 禁用状态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);textPass.setColleagueEnabled(false);}}@Overridepublic void actionPerformed(ActionEvent e) {System.out.println(e.toString());System.exit(0);}}
Mediator模式中的登场角色:
Mediator(仲裁者、中介者):
负责定义与Colleague角色进行通信和做出决定的接口(API)。在示例程序中,由Mediator接口扮演此角色。
ConcreteMediator(具体的仲裁者、中介者):
负责实现Mediator角色的接口(API),负责实际做出决定。
Colleague(同事):
ConcreteColleague(具体的同事):
负责实现Colleague角色的接口。
