在实际的工作小组的交流过程是,组员向仲裁者报告,仲裁者向组员下达指示,组员之间不再互相询问和指示。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框架中。

  

设计模式(十六)Mediator模式的更多相关文章

  1. 设计模式 ( 十六 ) 观察者模式Observer(对象行为型)

    设计模式 ( 十六 ) 观察者模式Observer(对象行为型) 1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来 ...

  2. 【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成 ...

  3. 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...

  4. 设计模式 ( 十九 ) 模板方法模式Template method(类行为型)

      设计模式 ( 十九 ) 模板方法模式Template method(类行为型) 1.概述 在面向对象开发过程中,通常我们会遇到这样的一个问题:我们知道一个算法所需的关键步骤,并确定了这些步骤的执行 ...

  5. 设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型)

      设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型) 1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的 ...

  6. 设计模式 ( 十六 ): Mediator中介者模式 -- 行为型

    1.概述 在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责,即将行为分布到各个对象中. 对于一个模块或者系统,可能由很多对象构成,而且这些对象 ...

  7. C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】

    一.引言   今天我们开始讲"行为型"设计模式的第三个模式,该模式是[迭代器模式],英文名称是:Iterator Pattern.还是老套路,先从名字上来看看."迭代器模 ...

  8. javascript设计模式学习之十六——状态模式

    一.状态模式的定义 状态模式的关键是区分事务内部和外部的状态,事务内部状态改变往往会带来事务的行为改变. 状态模式中有意思的一点是,一般我们谈到封装,都是优先封装对象的行为,而非对象的状态.但在状态模 ...

  9. 数据结构(十六)模式匹配算法--Brute Force算法和KMP算法

    一.模式匹配 串的查找定位操作(也称为串的模式匹配操作)指的是在当前串(主串)中寻找子串(模式串)的过程.若在主串中找到了一个和模式串相同的子串,则查找成功:若在主串中找不到与模式串相同的子串,则查找 ...

  10. java常用设计模式十:模板模式

    一.定义 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 如果上面的话不好理解,请看下面的例子 二.示例 1)定义一个模 ...

随机推荐

  1. 数据结构之二叉树篇卷三 -- 二叉树非递归遍历(With Java)

    Nonrecursive Traversal of Binary Tree First I wanna talk about why we should <code>Stack</c ...

  2. springboot jpa使用

    1.添加pom依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId ...

  3. SUSE Ceph 增加节点、减少节点、 删除OSD磁盘等操作 - Storage6

    一.测试环境描述 之前我们已快速部署好一套Ceph集群(3节点),现要测试在现有集群中在线方式增加节点 如下表中可以看到增加节点node004具体配置 主机名 Public网络 管理网络 集群网络 说 ...

  4. C语言I博客作业02

    这个作业属于那个课程  C语言程序设计I 这个作业要求在哪 https://edu.cnblogs.com/campus/zswxy/CST2019-3/homework/8656 我在这个课程的目标 ...

  5. 使用 Chrome 对长网页(知乎、微信公众号文章)进行完整截图

    当需要对一个较长的网页进行完整截图时,可以直接使用谷歌浏览器(Chrome)自带的截图功能完成,不需要依赖第三方截图软件. 1. 打开网页 以微信公众号的页面作为示例:https://mp.weixi ...

  6. struts 2.3.28+spring 4.2.5.RELEASE+hibernate 5.1.0.Final整合maven构建项目基本配置

    第一次写博客,主要也是记录给自己看的,可能很多比较熟的地方就没注释 用maven构建,ssh框架都是选用的最新的release版(感觉还是不要用beta),环境jdk1.8 tomcat8.0 mys ...

  7. Cocos2d-x入门之旅[1]场景

    在游戏开发过程中,你可能需要一个主菜单,几个关卡和一个END的界面,如何组织管理这些东西呢? 和其他游戏引擎类似,Cocos也使用了场景(Scene) 这个概念 试想象一部电影或是番剧,你不难发现它是 ...

  8. Kubernetes网络分析之Flannel

    Flannel是cereos开源的CNI网络插件,下图flannel官网提供的一个数据包经过封包.传输以及拆包的示意图,从这个图片中可以看出两台机器的docker0分别处于不同的段:10.1.20.1 ...

  9. Web安全之变量覆盖漏洞

    通常将可以用自定义的参数值替换原有变量值的情况称为变量覆盖漏洞.经常导致变量覆盖漏洞场景有:$$使用不当,extract()函数使用不当,parse_str()函数使用不当,import_reques ...

  10. [BZOJ1965][AHOI2005] 洗牌 - 扩展欧几里得

    题目描述 为了表彰小联为Samuel星球的探险所做出的贡献,小联被邀请参加Samuel星球近距离载人探险活动. 由于Samuel星球相当遥远,科学家们要在飞船中度过相当长的一段时间,小联提议用扑克牌打 ...