详解Java设计模式编程中的中介者模式

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

中介者模式的结构
       中介者模式又称为调停者模式,从类图中看,共分为3部分:
 抽象中介者:定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信。一般包括一个或几个抽象的事件方法,并由子类去实现。
中介者实现类:从抽象中介者继承而来,实现抽象中介者中定义的事件方法。从一个同事类接收消息,然后通过消息影响其他同时类。
同事类:如果一个对象会影响其他的对象,同时也会被其他对象影响,那么这两个对象称为同事类。在类图中,同事类只有一个,这其实是现实的省略,在实际应用中,同事类一般由多个组成,他们之间相互影响,相互依赖。同事类越多,关系越复杂。并且,同事类也可以表现为继承了同一个抽象类的一组实现组成。在中介者模式中,同事类之间必须通过中介者才能进行消息传递。
为什么要使用中介者模式
       一般来说,同事类之间的关系是比较复杂的,多个同事类之间互相关联时,他们之间的关系会呈现为复杂的网状结构,这是一种过度耦合的架构,即不利于类的复用,也不稳定。例如在下图中,有六个同事类对象,假如对象1发生变化,那么将会有4个对象受到影响。如果对象2发生变化,那么将会有5个对象受到影响。也就是说,同事类之间直接关联的设计是不好的。

如果引入中介者模式,那么同事类之间的关系将变为星型结构,从图中可以看到,任何一个类的变动,只会影响的类本身,以及中介者,这样就减小了系统的耦合。一个好的设计,必定不会把所有的对象关系处理逻辑封装在本类中,而是使用一个专门的类来管理那些不属于自己的行为。


下面给出具体的代码例子,对比通用类图增加了AbstractColleague抽象同事类和AbstractMediator抽象中介者,另外就是两个具体同事类和一个具体中介者,代码中有较多注释,相应类图也不给出了,应该不难理解的:
 
同事类族:

//抽象同事类
abstract class AbstractColleague {
  protected AbstractMediator mediator; 

  /**既然有中介者,那么每个具体同事必然要与中介者有联系,
   * 否则就没必要存在于 这个系统当中,这里的构造函数相当
   * 于向该系统中注册一个中介者,以取得联系
   */
  public AbstractColleague(AbstractMediator mediator) {
    this.mediator = mediator;
  } 

  // 在抽象同事类中添加用于与中介者取得联系(即注册)的方法
  public void setMediator(AbstractMediator mediator) {
    this.mediator = mediator;
  }
} 

//具体同事A
class ColleagueA extends AbstractColleague { 

  //每个具体同事都通过父类构造函数与中介者取得联系
  public ColleagueA(AbstractMediator mediator) {
    super(mediator);
  } 

  //每个具体同事必然有自己分内的事,没必要与外界相关联
  public void self() {
    System.out.println("同事A --> 做好自己分内的事情 ...");
  } 

  //每个具体同事总有需要与外界交互的操作,通过中介者来处理这些逻辑并安排工作
  public void out() {
    System.out.println("同事A --> 请求同事B做好分内工作 ...");
    super.mediator.execute("ColleagueB", "self");
  }
} 

//具体同事B
class ColleagueB extends AbstractColleague { 

  public ColleagueB(AbstractMediator mediator) {
    super(mediator);
  } 

  public void self() {
    System.out.println("同事B --> 做好自己分内的事情 ...");
  } 

  public void out() {
    System.out.println("同事B --> 请求同事A做好分内工作 ...");
    super.mediator.execute("ColleagueA", "self");
  }
}

中介者类族:

//抽象中介者
abstract class AbstractMediator { 

  //中介者肯定需要保持有若干同事的联系方式
  protected Hashtable<String, AbstractColleague> colleagues = new Hashtable<String, AbstractColleague>(); 

  //中介者可以动态地与某个同事建立联系
  public void addColleague(String name, AbstractColleague c) {
    this.colleagues.put(name, c);
  }   

  //中介者也可以动态地撤销与某个同事的联系
  public void deleteColleague(String name) {
    this.colleagues.remove(name);
  } 

  //中介者必须具备在同事之间处理逻辑、分配任务、促进交流的操作
  public abstract void execute(String name, String method);
} 

//具体中介者
class Mediator extends AbstractMediator{ 

  //中介者最重要的功能,来回奔波与各个同事之间
  public void execute(String name, String method) { 

    if("self".equals(method)){ //各自做好分内事
      if("ColleagueA".equals(name)) {
        ColleagueA colleague = (ColleagueA)super.colleagues.get("ColleagueA");
        colleague.self();
      }else {
        ColleagueB colleague = (ColleagueB)super.colleagues.get("ColleagueB");
        colleague.self();
      }
    }else { //与其他同事合作
      if("ColleagueA".equals(name)) {
        ColleagueA colleague = (ColleagueA)super.colleagues.get("ColleagueA");
        colleague.out();
      }else {
        ColleagueB colleague = (ColleagueB)super.colleagues.get("ColleagueB");
        colleague.out();
      }
    }
  }
}

测试类:

//测试类
public class Client {
  public static void main(String[] args) { 

    //创建一个中介者
    AbstractMediator mediator = new Mediator(); 

    //创建两个同事
    ColleagueA colleagueA = new ColleagueA(mediator);
    ColleagueB colleagueB = new ColleagueB(mediator); 

    //中介者分别与每个同事建立联系
    mediator.addColleague("ColleagueA", colleagueA);
    mediator.addColleague("ColleagueB", colleagueB); 

    //同事们开始工作
    colleagueA.self();
    colleagueA.out();
    System.out.println("======================合作愉快,任务完成!\n"); 

    colleagueB.self();
    colleagueB.out();
    System.out.println("======================合作愉快,任务完成!");
  }
}

测试结果:

同事A --> 做好自己分内的事情 ...
同事A --> 请求同事B做好分内工作 ...
同事B --> 做好自己分内的事情 ...
======================合作愉快,任务完成! 

同事B --> 做好自己分内的事情 ...
同事B --> 请求同事A做好分内工作 ...
同事A --> 做好自己分内的事情 ...
======================合作愉快,任务完成!

虽然以上代码中只有两个具体同事类,并且测试类中也只是创建了两个同事,但是这些我们都可以根据中介者模式的宗旨进行适当地扩展,即增加具体同事类,然后中介者就得担负更加重的任务了。为啥?我们看到上面具体中介者类Mediator中的execute()方法中现在就有一堆冗长的判断代码了。虽然可以把它分解并增加到Mediator类中的其它private方法中,但是具体的业务逻辑是少不了的。
 
所以,在解耦同事类之间的联系的同时,中介者自身也不免任务过重,因为几乎所有的业务逻辑都交代到中介者身上了,可谓是“万众期待”的一个角色了。这就是中介者模式的不足之处了 。
此外,上面这个代码例子是相当理想的了,有时候我们根本抽取不了“同事”之间的共性来形成一个AbstractColleague抽象同事类,这也大大增加了中介者模式的使用难度。  
修改:
由于上面代码实现中存在 benjielin 前辈提出的“双向关联暴露在App中”的不足之处,根据给出的改进方法2,修改上面代码,如下:
 
修改后的同事类族:

//抽象同事类
abstract class AbstractColleague {
  protected AbstractMediator mediator;   

  //舍去在构造函数中建立起与中介者的联系
// public AbstractColleague(AbstractMediator mediator) {
//   this.mediator = mediator;
// } 

  // 在抽象同事类中添加用于与中介者取得联系(即注册)的方法
  public void setMediator(AbstractMediator mediator) {
    this.mediator = mediator;
  }
} 

//具体同事A
class ColleagueA extends AbstractColleague { 

  //舍去在构造函数中建立起与中介者的联系
// public ColleagueA(AbstractMediator mediator) {
//   super(mediator);
// } 

  //每个具体同事必然有自己分内的事,没必要与外界相关联
  public void self() {
    System.out.println("同事A --> 做好自己分内的事情 ...");
  } 

  //每个具体同事总有需要与外界交互的操作,通过中介者来处理这些逻辑并安排工作
  public void out() {
    System.out.println("同事A --> 请求同事B做好分内工作 ...");
    super.mediator.execute("ColleagueB", "self");
  }
} 

//具体同事B
class ColleagueB extends AbstractColleague {
  //舍去在构造函数中建立起与中介者的联系
// public ColleagueB(AbstractMediator mediator) {
//   super(mediator);
// } 

  public void self() {
    System.out.println("同事B --> 做好自己分内的事情 ...");
  } 

  public void out() {
    System.out.println("同事B --> 请求同事A做好分内工作 ...");
    super.mediator.execute("ColleagueA", "self");
  }
}

修改后的中介者:

 //抽象中介者
abstract class AbstractMediator { 

  //中介者肯定需要保持有若干同事的联系方式
  protected Hashtable<String, AbstractColleague> colleagues = new Hashtable<String, AbstractColleague>(); 

  //中介者可以动态地与某个同事建立联系
  public void addColleague(String name, AbstractColleague c) { 

    // 在中介者这里帮助具体同事建立起于中介者的联系
    c.setMediator(this);
    this.colleagues.put(name, c);
  }   

  //中介者也可以动态地撤销与某个同事的联系
  public void deleteColleague(String name) {
    this.colleagues.remove(name);
  } 

  //中介者必须具备在同事之间处理逻辑、分配任务、促进交流的操作
  public abstract void execute(String name, String method);
}
//测试类
public class Client {
  public static void main(String[] args) { 

    //创建一个中介者
    AbstractMediator mediator = new Mediator(); 

    //不用构造函数为具体同事注册中介者来取得联系了
//   ColleagueA colleagueA = new ColleagueA(mediator);
//   ColleagueB colleagueB = new ColleagueB(mediator); 

    ColleagueA colleagueA = new ColleagueA();
    ColleagueB colleagueB = new ColleagueB(); 

    //中介者分别与每个同事建立联系
    mediator.addColleague("ColleagueA", colleagueA);
    mediator.addColleague("ColleagueB", colleagueB); 

    //同事们开始工作
    colleagueA.self();
    colleagueA.out();
    System.out.println("======================合作愉快,任务完成!\n"); 

    colleagueB.self();
    colleagueB.out();
    System.out.println("======================合作愉快,任务完成!");
  }
}

测试之后的结果与修改前一样。

(0)

相关推荐

  • java设计模式之中介者模式

    中介者模式 面向对象设计鼓励将行为分布到各个对象中, 这种分布可能会导致对象间有许多连接. 在最坏的情况下, 每一个对象都需要知道其他所有对象. 虽然将一个系统分割成许多对象可增强可复用性, 但是对象间相互连接的激增又会降低其可复用性. 大量的连接关系使得一个对象不可能在没有其他对象的协助下工作(系统表现为一个不可分割的整体), 此时再对系统行为进行任何较大改动就十分困难. 因为行为被分布在许多对象中, 结果是不得不定义很多子类以定制系统的行为. 由此我们引入了中介者对象Mediator: 通过

  • 轻松掌握java中介者模式

    定义:用来降低多个对象和类之间的通信复杂性.中介者模式属于行为型模式. 特点: 1.降低了类的复杂度,将一对多转化成了一对一. 2.各个类之间的解耦. 3.符合迪米特原则. 企业级开发和常用框架中的应用:mvc模式中的c 具体实例: public class Demo { public static void main(String[] args) { Mediator m = new Mediator(); Department d1 = new Department(m, "开发部"

  • Java设计模式之中介者模式(Mediator Pattern)简介

    Java设计模式的中介者模式是行为模式之一.定义一个中介对象来封装系列对象之间的交互.中介者使各个对象不需要显式地相互引用,从而使其耦合性松散,并且可以独立地改变他们之间的交互. 如下图所示: 生产者.消费者.代理商之间的中介模式实例: public abstract class PersonColleague { protected Mediator mediator; public Mediator getMediator() { return mediator; } public void

  • 设计模式之中介者模式_动力节点Java学院整理

    定义:用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互. 类型:行为类模式 类图: 中介者模式的结构 中介者模式又称为调停者模式,从类图中看,共分为3部分: 抽象中介者:定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信.一般包括一个或几个抽象的事件方法,并由子类去实现. 中介者实现类:从抽象中介者继承而来,实现抽象中介者中定义的事件方法.从一个同事类接收消息,然后通过消息影响其他同时类. 同事类:如果一个对象会

  • 详解Java设计模式编程中的中介者模式

    定义:用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互. 类型:行为类模式 类图: 中介者模式的结构        中介者模式又称为调停者模式,从类图中看,共分为3部分:  抽象中介者:定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信.一般包括一个或几个抽象的事件方法,并由子类去实现. 中介者实现类:从抽象中介者继承而来,实现抽象中介者中定义的事件方法.从一个同事类接收消息,然后通过消息影响其他同时类. 同事类

  • 详解Java设计模式编程中的访问者模式

    定义:封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作. 类型:行为类模式 类图: 例子: 例如,思考一下添加不同类型商品的购物车,当点击结算的时候,它计算出所有不同商品需付的费用.现在,计算逻辑即为计算这些不同类型商品的价格.或者说通过访问者模式我们把此逻辑转移到了另外一个类上面.让我们实现这个访问者模式的例子. 为了实现访问者模式,最先需要做的是创建能够被添加到购物车中代表不同类型商品(itemElement)的类. ItemElement

  • 详解Java设计模式编程中的策略模式

    定义:定义一组算法,将每个算法都封装起来,并且使他们之间可以互换. 类型:行为类模式 类图: 策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换.在前面说过的行为类模式中,有一种模式也是关注对算法的封装--模版方法模式,对照类图可以看到,策略模式与模版方法模式的区别仅仅是多了一个单独的封装类Context,它与模版方法模式的区别在于:在模版方法模式中,调用算法的主体在抽象的父类中,而在策略模式中,调用算法的主体则是封装到了封装类Context中

  • 详解Java设计模式编程中的Flyweight享元模式的开发结构

    享元(Flyweight)模式:通过共享技术以便有效的支持大量细粒度的对象. 享元模式在阎宏的<java与模式>中分为单纯享元模式和复合享元模式,复合模式的复合享元是不可以共享的,享元对象能做到共享的关键是区分内蕴态(Internal State)和外蕴态( External State).这两个"蕴态"翻译的太难懂,我不是说翻译的不好,可能是我理解能力差,还是<Design Pattern Elements of Reusable Object-Oriented S

  • 详解Java设计模式编程中的依赖倒置原则

    定义: 高层模块不应该依赖低层模块,二者都应该依赖其抽象:抽象不应该依赖细节:细节应该依赖抽象. 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块,负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率.          依赖倒置原则基于这样一个事实:

  • 详解Java设计模式编程中命令模式的项目结构实现

    正论: 命令模式把一个请求或者操作封装到一个对象中.命令模式运行系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能. 通俗: 其实很好理解.命令模式,关心的就是命令(或者称为操作).打个比方.在一个公司里面,整个运作就像一个系统.某个boss发布了一个命令,中层领导接到这个命令,然后指派给具体负责这个员工.整个流程很清晰吧.有一个需求,如何将这个流程固定下来,形成一个系统.我们只要抓住了重点:命令.将它抽取出来,其他的都迎刃而解了.抽取出命令,封装成一个独

  • 详解Java设计模式编程中的里氏替换原则

    定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型. 定义2:所有引用基类的地方必须能透明地使用其子类的对象. 问题由来:有一功能P1,由类A完成.现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成.新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障. 解决方

  • 详解Python设计模式编程中观察者模式与策略模式的运用

    观察者模式 观察者模式:又叫发布订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时,会通知所有观察者对象,是他们能自动更新自己. 代码结构 class Topic(object): """主题类.保存所有观察者实例的引用,每个主题都可以有很多观察者 可以增加和删除观察者""" def __init__(self): self.obs = [] def Attach(self, ob): se

  • 详解Java多线程编程中的线程同步方法

    1.多线程的同步: 1.1.同步机制: 在多线程中,可能有多个线程试图访问一个有限的资源,必须预防这种情况的发生.所以引入了同步机制:在线程使用一个资源时为其加锁,这样其他的线程便不能访问那个资源了,直到解锁后才可以访问. 1.2.共享成员变量的例子: 成员变量与局部变量: 成员变量: 如果一个变量是成员变量,那么多个线程对同一个对象的成员变量进行操作,这多个线程是共享一个成员变量的. 局部变量: 如果一个变量是局部变量,那么多个线程对同一个对象进行操作,每个线程都会有一个该局部变量的拷贝.他们

  • 详解Java多线程编程中线程的启动、中断或终止操作

    线程启动: 1.start() 和 run()的区别说明 start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法.start()不能被重复调用. run() : run()就和普通的成员方法一样,可以被重复调用.单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程! 下面以代码来进行说明. class MyThread extends Thread{ public void run(){ ... } }; MyThread mythread = new

随机推荐