5. 中介者(Mediator)

Intent

集中相关对象之间复杂的沟通和控制方式。

Class Diagram

  • Mediator:中介者,定义一个接口用于与各同事(Colleague)对象通信。
  • Colleague:同事,相关对象

设计模式 - 中介者 - 图1

Implementation

Alarm(闹钟)、CoffeePot(咖啡壶)、Calendar(日历)、Sprinkler(喷头)是一组相关的对象,在某个对象的事件产生时需要去操作其它对象,形成了下面这种依赖结构:

设计模式 - 中介者 - 图2

使用中介者模式可以将复杂的依赖结构变成星形结构:

设计模式 - 中介者 - 图3

  1. public abstract class Colleague {
  2. public abstract void onEvent(Mediator mediator);
  3. }
  1. public class Alarm extends Colleague {
  2. @Override
  3. public void onEvent(Mediator mediator) {
  4. mediator.doEvent("alarm");
  5. }
  6. public void doAlarm() {
  7. System.out.println("doAlarm()");
  8. }
  9. }
  1. public class CoffeePot extends Colleague {
  2. @Override
  3. public void onEvent(Mediator mediator) {
  4. mediator.doEvent("coffeePot");
  5. }
  6. public void doCoffeePot() {
  7. System.out.println("doCoffeePot()");
  8. }
  9. }
  1. public class Calender extends Colleague {
  2. @Override
  3. public void onEvent(Mediator mediator) {
  4. mediator.doEvent("calender");
  5. }
  6. public void doCalender() {
  7. System.out.println("doCalender()");
  8. }
  9. }
  1. public class Sprinkler extends Colleague {
  2. @Override
  3. public void onEvent(Mediator mediator) {
  4. mediator.doEvent("sprinkler");
  5. }
  6. public void doSprinkler() {
  7. System.out.println("doSprinkler()");
  8. }
  9. }
  1. public abstract class Mediator {
  2. public abstract void doEvent(String eventType);
  3. }
  1. public class ConcreteMediator extends Mediator {
  2. private Alarm alarm;
  3. private CoffeePot coffeePot;
  4. private Calender calender;
  5. private Sprinkler sprinkler;
  6. public ConcreteMediator(Alarm alarm, CoffeePot coffeePot, Calender calender, Sprinkler sprinkler) {
  7. this.alarm = alarm;
  8. this.coffeePot = coffeePot;
  9. this.calender = calender;
  10. this.sprinkler = sprinkler;
  11. }
  12. @Override
  13. public void doEvent(String eventType) {
  14. switch (eventType) {
  15. case "alarm":
  16. doAlarmEvent();
  17. break;
  18. case "coffeePot":
  19. doCoffeePotEvent();
  20. break;
  21. case "calender":
  22. doCalenderEvent();
  23. break;
  24. default:
  25. doSprinklerEvent();
  26. }
  27. }
  28. public void doAlarmEvent() {
  29. alarm.doAlarm();
  30. coffeePot.doCoffeePot();
  31. calender.doCalender();
  32. sprinkler.doSprinkler();
  33. }
  34. public void doCoffeePotEvent() {
  35. // ...
  36. }
  37. public void doCalenderEvent() {
  38. // ...
  39. }
  40. public void doSprinklerEvent() {
  41. // ...
  42. }
  43. }
  1. public class Client {
  2. public static void main(String[] args) {
  3. Alarm alarm = new Alarm();
  4. CoffeePot coffeePot = new CoffeePot();
  5. Calender calender = new Calender();
  6. Sprinkler sprinkler = new Sprinkler();
  7. Mediator mediator = new ConcreteMediator(alarm, coffeePot, calender, sprinkler);
  8. // 闹钟事件到达,调用中介者就可以操作相关对象
  9. alarm.onEvent(mediator);
  10. }
  11. }
  1. doAlarm()
  2. doCoffeePot()
  3. doCalender()
  4. doSprinkler()

中介者模式总结

中介者模式的主要优点

  • 中介者模式简化了对象之间的交互,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互,一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星型结构。
  • 中介者模式可将各同事对象解耦。中介者有利于各同事之间的松耦合,我们可以独立的改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好地符合 “开闭原则”。
  • 可以减少子类生成,中介者将原本分布于多个对象间的行为集中在一起,改变这些行为只需生成新的中介者子类即可,这使各个同事类可被重用,无须对同事类进行扩展。

    中介者模式的主要缺点

  • 具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。(也就是把具体同事类之间的交互复杂性集中到了中介者类中,结果中介者成了最复杂的类)

    适用场景

  • 系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。

  • 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
  • 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的具体中介者类。