设计模式(十六)Mediator模式

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

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

  对话框有以下一些要求:

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

  

1 public interface Mediator {
2     public abstract void createColleagues();
3     public abstract void colleagueChanged();
4 }

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

 

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

 

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

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

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

 1 import java.awt.Button;
 2 
 3 public class ColleagueButton extends Button implements Colleague {
 4     private Mediator mediator;
 5 
 6     public ColleagueButton(String caption) {
 7         super(caption);
 8     }
 9 
10     public void setMediator(Mediator mediator) { // 保存Mediator
11         this.mediator = mediator;
12     }
13 
14     public void setColleagueEnabled(boolean enabled) { // Mediator下达启用/禁用的指示
15         setEnabled(enabled);
16     }
17 }

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

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

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

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

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

 1 import java.awt.Checkbox;
 2 import java.awt.CheckboxGroup;
 3 import java.awt.event.ItemListener;
 4 import java.awt.event.ItemEvent;
 5 
 6 public class ColleagueCheckbox extends Checkbox implements ItemListener, Colleague {
 7     private Mediator mediator;
 8 
 9     public ColleagueCheckbox(String caption, CheckboxGroup group, boolean state) { // 构造函数
10         super(caption, group, state);
11     }
12 
13     public void setMediator(Mediator mediator) { // 保存Mediator
14         this.mediator = mediator;
15     }
16 
17     public void setColleagueEnabled(boolean enabled) { // Mediator下达启用/禁用指示
18         setEnabled(enabled);
19     }
20 
21     public void itemStateChanged(ItemEvent e) { // 当状态发生变化时通知Mediator
22         mediator.colleagueChanged();
23     }
24 }

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

  1 import java.awt.Frame;
  2 import java.awt.Label;
  3 import java.awt.Color;
  4 import java.awt.CheckboxGroup;
  5 import java.awt.GridLayout;
  6 import java.awt.event.ActionListener;
  7 import java.awt.event.ActionEvent;
  8 
  9 public class LoginFrame extends Frame implements ActionListener, Mediator {
 10     private ColleagueCheckbox checkGuest;
 11     private ColleagueCheckbox checkLogin;
 12     private ColleagueTextField textUser;
 13     private ColleagueTextField textPass;
 14     private ColleagueButton buttonOk;
 15     private ColleagueButton buttonCancel;
 16 
 17     // 构造函数。
 18     // 生成并配置各个Colleague后,显示对话框。
 19     public LoginFrame(String title) {
 20         super(title);
 21         setBackground(Color.lightGray);
 22         // 使用布局管理器生成4×2窗格
 23         setLayout(new GridLayout(4, 2));
 24         // 生成各个Colleague
 25         createColleagues();
 26         // 配置
 27         add(checkGuest);
 28         add(checkLogin);
 29         add(new Label("Username:"));
 30         add(textUser);
 31         add(new Label("Password:"));
 32         add(textPass);
 33         add(buttonOk);
 34         add(buttonCancel);
 35         // 设置初始的启用起用/禁用状态
 36         colleagueChanged();
 37         // 显示
 38         pack();
 39         show();
 40     }
 41 
 42     // 生成各个Colleague。
 43     public void createColleagues() {
 44         // 生成
 45         CheckboxGroup g = new CheckboxGroup();
 46         checkGuest = new ColleagueCheckbox("Guest", g, true);
 47         checkLogin = new ColleagueCheckbox("Login", g, false);
 48         textUser = new ColleagueTextField("", 10);
 49         textPass = new ColleagueTextField("", 10);
 50         textPass.setEchoChar('*');
 51         buttonOk = new ColleagueButton("OK");
 52         buttonCancel = new ColleagueButton("Cancel");
 53         // 设置Mediator,事先告诉这些组员“我是仲裁者,有什么问题的可以像我报告。”
 54         checkGuest.setMediator(this);
 55         checkLogin.setMediator(this);
 56         textUser.setMediator(this);
 57         textPass.setMediator(this);
 58         buttonOk.setMediator(this);
 59         buttonCancel.setMediator(this);
 60         // 设置Listener
 61         checkGuest.addItemListener(checkGuest);
 62         checkLogin.addItemListener(checkLogin);
 63         textUser.addTextListener(textUser);
 64         textPass.addTextListener(textPass);
 65         buttonOk.addActionListener(this);
 66         buttonCancel.addActionListener(this);
 67     }
 68 
 69     // 接收来自于Colleage的通知然后判断各Colleage的启用/禁用状态。
 70     public void colleagueChanged() {
 71         if (checkGuest.getState()) { // Guest mode
 72             textUser.setColleagueEnabled(false);
 73             textPass.setColleagueEnabled(false);
 74             buttonOk.setColleagueEnabled(true);
 75         } else { // Login mode
 76             textUser.setColleagueEnabled(true);
 77             userpassChanged();
 78         }
 79     }
 80 
 81     // 当textUser或是textPass文本输入框中的文字发生变化时
 82     // 判断各Colleage的启用/禁用状态
 83     private void userpassChanged() {
 84         if (textUser.getText().length() > 0) {
 85             textPass.setColleagueEnabled(true);
 86             if (textPass.getText().length() > 0) {
 87                 buttonOk.setColleagueEnabled(true);
 88             } else {
 89                 buttonOk.setColleagueEnabled(false);
 90             }
 91         } else {
 92             textPass.setColleagueEnabled(false);
 93             buttonOk.setColleagueEnabled(false);
 94         }
 95     }
 96 
 97     public void actionPerformed(ActionEvent e) {
 98         System.out.println(e.toString());
 99         System.exit(0);
100     }
101 }

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

1 import java.awt.*;
2 import java.awt.event.*;
3 
4 public class Main {
5     static public void main(String args[]) {
6         new LoginFrame("Mediator Sample");
7     }
8 }

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

 

 

 

 

 

 

  

 

posted @ 2018-04-12 08:20  BigJunOba  阅读(357)  评论(0编辑  收藏  举报