说到中介大家都不会陌生,买房子租房子有中介,出国留学有中介,买卖二手车还是有中介。那么中介到底是个什么角色呢?实际上,中介就是让买卖双方不必面对面直接交流,由他/她来完成买卖双方的交易,达到解耦买卖人,同时给买卖双方带来方便的一个职业角色。对于应用开发来说,代码就是来源于生活,就是生活的抽象,因此,中介这种模式也应用在应用开发中,这就是我下面要介绍的----中介者模式。


1.中介者模式

中介者模式(Mediator Pattern) 定义了一个对象, 这个对象封装了其它对象之间的交互行为。

这个定义的对象通常我门称为Mediator, 它是一个“中介”, 封装的是其它对象之间的交互这种行为,所以,中介者模式是一种行为模式。中介者模式的引入,多个对象由原来的互相直接交互,变成了通过Mediator进行交互,这样,交互对象之间就不必相互依赖或者关联,于是就松散了它们之间的耦合关系。中介者模式的结构图如下:

从类图中可以看到,中介与交互对象Colleague关联, 而交互对象之间没有关联,这就是说,随着交互对象的增长,Mediator所要关联的对象也会越来越多,实际上就是把关联转移到了Mediator, Mediator本身的逻辑也会越来越复杂。再从时序图上看一下交互发生时的整个过程:

可以清楚的看到Colleague1和Colleague2之间的交互过程,都是通过Mediator进行的。简单地概括起来,中介者模式提供的解决方案就是:

  • 定义一个Mediator对象来封装对象的交互
  • 对象通过Mediator作为代理,与其它对象进行交互

3.代码实现

典型的中介者模式应用的场景,就是将其应用在GUI应用上各种按钮、控件之间的通信,比如这里设计一个简化的场景,有三个按钮:按钮一(Btn1)、按钮二(Btn2)、按钮三(Btn3),当你点击按钮一时,按钮一置灰,此时点击按钮二,按钮二置灰。按钮一恢复,即Radio button,想想过去的老式收音机,一次按钮不能连续按两次。

点击按钮即执行一次命令,即按按钮具有执行命令的行为,故而可以抽象出一个interface来定义这种执行命令的行为。每个实现它的按钮,被点击的时候,都应该执行action方法。

interface Action {
void action();
}

中介者interface Mediator, 定义了一系列的接口。btn1(),btn2(),btn3()供按钮btn1,btn2,btn3调用,registerBtn1(), registerBtn2(), registerBtn3()在Mediator中分别注册三个按钮。

interface Mediator {
void btn1();
void btn2();
void btn3(); void registerBtn1(Btn1 b);
void registerBtn2(Btn2 b);
void registerBtn3(Btn3 b);
}

BtnMediator是Mediator的实现类,它关联了所有按钮(Btn1, Btn2, Btn3), 实现了接口的方法。

class BtnMediator implements Mediator {

    Btn1 btn1;
Btn2 btn2;
Btn3 btn3; @Override
public void btn1() {
btn1.setEnabled(false);
btn2.setEnabled(true);
btn3.setEnabled(true);
} @Override
public void btn2() {
btn1.setEnabled(true);
btn2.setEnabled(false);
btn3.setEnabled(true);
} @Override
public void btn3() {
btn1.setEnabled(true);
btn2.setEnabled(true);
btn3.setEnabled(false);
} @Override
public void registerBtn1(Btn1 b) {
btn1 = b;
} @Override
public void registerBtn2(Btn2 b) {
btn2 = b;
} @Override
public void registerBtn3(Btn3 b) {
btn3 = b;
}
}

定义三个按钮,它们都继承了JButton, 并且实现了Action,这三个按钮就是交互对象。需要注意的就是按钮与Mediator相互关联,所以按钮的属性中定义了一个Mediator成员变量, 构造器中包含有初始化JButton对象的方法,比如super("btn1")定义按钮显示名称,addActionLIstener(al)是为按钮添加监听,因为Java中,按钮是事件驱动的。med.registerBtnx()即注册该按钮到Mediator中。

class Btn1 extends JButton implements Action {

    Mediator med;

    public Btn1(ActionListener al, Mediator m) {
super("btn1");
addActionListener(al);
this.med = m;
med.registerBtn1(this);
} @Override
public void action() {
med.btn1();
}
} class Btn2 extends JButton implements Action { Mediator med; public Btn2(ActionListener al, Mediator m) {
super("btn2");
addActionListener(al);
med = m;
med.registerBtn2(this);
} @Override
public void action() {
med.btn2();
}
} class Btn3 extends JButton implements Action { Mediator med; public Btn3(ActionListener al, Mediator m) {
super("btn3");
addActionListener(al);
med = m;
med.registerBtn3(this);
} @Override
public void action() {
med.btn3();
}
}

最后定义了本例子的演示入口,MediatorDemo继承JFrame,这种写法也是Swing当中常见的写法。 定义了一个静态内部类MyListener 监听点击按钮事件。 在构造器中初始化此控件。运行main方法。

public class MediatorDemo extends JFrame {
Mediator med = new BtnMediator(); public MediatorDemo() {
ActionListener al = new MyListener();
add(new Btn1(al, med));
add(new Btn2(al, med));
add(new Btn3(al, med));
setSize(300,100);
setLayout(new FlowLayout());
setVisible(true);
} static class MyListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Action a = (Action) e.getSource();
a.action();
}
} public static void main(String[] args) {
new MediatorDemo();
}
}

结果:

稍等片刻,桌面弹出一个面板,面板上有三个按钮,点击btn1, 置灰; 再点击btn3, btn3置灰,btn1恢复。


4.总结

前面的章节中也反复提到过,中介者模式就是封装一系列对象的交互行为,并通过实现了一个Radio Button的例子演示了中介者模式的应用。GUI中,各种控件之间的通信,都可以通过Mediator来封装。在实际开发过程中,经常会出现对象之间交互的情况,那么这些场景是否适合应用中介者模式,就需要具体问题具体分析了,因为如果交互的对象增多,那么Mediator的方法也会不断增加,如果不同对象之间的交互上依赖于更多其它对象,那么Mediator也就会依赖很多其它对象。所以,想应用中介者模式,就需要把对象之间的通信行为定义的比较独立,比如按下btn1,btn1就置灰,btn2,btn3设置为true......而无需再依赖其它不确定的条件。

Java设计模式----中介者模式的更多相关文章

  1. JAVA 设计模式 中介者模式

    用途 中介者模式 (Mediator) 用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 中介者模式是一种行为型模式. 结 ...

  2. Java设计模式-中介者模式(Mediator)

    中介者模式也是用来降低类类之间的耦合的,因为如果类类之间有依赖关系的话,不利于功能的拓展和维护,因为只要修改一个对象,其它关联的对象都得进行修改.如果使用中介者模式,只需关心和Mediator类的关系 ...

  3. Java设计模式—中介者模式

    中介者模式是一种并不常用的模式,在此简单阐述阐述. 定义:用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互. 类型:行为类模式 ...

  4. Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景

    我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...

  5. java设计模式6——代理模式

    java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...

  6. Java设计模式——装饰者模式

    JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...

  7. 7. 星际争霸之php设计模式--中介者模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  8. 浅析JAVA设计模式之工厂模式(一)

    1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...

  9. JAVA设计模式--装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...

随机推荐

  1. python爬虫之scrapy

    架构概览 本文档介绍了Scrapy架构及其组件之间的交互. 概述 接下来的图表展现了Scrapy的架构,包括组件及在系统中发生的数据流的概览(绿色箭头所示). 下面对每个组件都做了简单介绍,并给出了详 ...

  2. proposal-cancelable-promises

    fetch 从来就没行过,最大的优势就是"新标准",但是 proposal-cancelable-promises 被 withdrawn,就导致了 fetch 发起的请求不可能被 ...

  3. sublime3支持es6语法和vue彩色显示

    支持ES6语法设置: 首先安装nodejs 当然你可以使用其它诸如jsc之类的环境来运行js, 本文使用的是nodejs. 首先确保你的电脑已经安装好nodejs, 并已将其添加到环境变量中 (一般安 ...

  4. 修改CKplayer.js 源码解决移动端浏览器全屏不能限制快进的问题

    原文地址:https://www.cnblogs.com/jying/p/9642445.html,转载请说明出处. 最近项目需要播放视频且限制未观看部分的快进功能,找了两款js插件ckplayer和 ...

  5. JDK中的注解简单了解

    0.注解(注解是给编译器看的东东) 注解的定义方式是@Interface,注解属性定义是类似于普通类的方法定义的,注解属性赋值是使用default关键字完成的,如下图所示 注解在定义时可以给默认值,也 ...

  6. canvas刮刮乐游戏等

    裁剪 ctx.clip():当前路径外的区域不再绘制 <canvas id="cans" width=500 height=500></canvas> &l ...

  7. 数据库启动windows

    1.上 MongoDB官网下载数据库,下载之后选择自己想放的文件夹要记住文件夹位置,比如我下载之后就放在D盘,改文件夹为 mongodb 2.启动之前要给mongodb指定一个文件夹,这里取名为&qu ...

  8. 微信小程序页面跳转 的几种方式

    最近在做微信小程序,碰到页面跳转的问题,总结一下页面之间跳转的方式 一.wx.navigateTo(OBJECT) 这是最普遍的一种跳转方式,其官方解释为:“保留当前页面,跳转到应用内的某个页面” 类 ...

  9. sqlserver truncate清空表时候,无法删除 'B表',因为该表正由一个 FOREIGN KEY 约束引用。

    外键: 查询:select object_name(a.parent_object_id) 'tables'  from sys.foreign_keys a  where a.referenced_ ...

  10. 从汇编层面解释switch语句判断快速的原因

      源码如下: #include <stdio.h>   void main(){     int flag;     flag=1;     switch (flag){         ...