CHARLIE SAYS

查理如是说
DATE 2026-08-24
THEME
SERIES / DESIGN_PATTERNS / P-114 · 设计模式

设计模式 020:中介者(Mediator)

中介者模式(Mediator pattern)用中介对象来集中相关对象之间复杂的沟通和控制方式。各同事对象之间不再直接引用,而是统一通过中介者交互,把网状依赖变成星形结构。

意图

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

类图

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

原文图片丢失,据文字重绘。

classDiagram
    class Colleague {
        <<abstract>>
        +onEvent(Mediator)
    }
    class Alarm
    class CoffeePot
    class Calender
    class Sprinkler
    class Mediator {
        <<abstract>>
        +doEvent(String)
    }
    class ConcreteMediator {
        -Alarm alarm
        -CoffeePot coffeePot
        -Calender calender
        -Sprinkler sprinkler
        +doEvent(String)
    }
    Colleague <|-- Alarm
    Colleague <|-- CoffeePot
    Colleague <|-- Calender
    Colleague <|-- Sprinkler
    Mediator <|-- ConcreteMediator
    ConcreteMediator o-- Alarm
    ConcreteMediator o-- CoffeePot
    ConcreteMediator o-- Calender
    ConcreteMediator o-- Sprinkler
    Colleague ..> Mediator : onEvent 通知

实现

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

graph LR
    Alarm --> CoffeePot
    CoffeePot --> Calender
    Calender --> Sprinkler
    Sprinkler --> Alarm
    Alarm --> Calender
    CoffeePot --> Sprinkler

使用中介者模式可以将复杂的依赖结构变成星形结构(原文图片丢失,据文字重绘):

graph LR
    Alarm --> Mediator
    CoffeePot --> Mediator
    Calender --> Mediator
    Sprinkler --> Mediator
    Mediator --> Alarm
    Mediator --> CoffeePot
    Mediator --> Calender
    Mediator --> Sprinkler

同事类只依赖 Mediator 抽象,事件发生时把处理权交给中介者:

public abstract class Colleague {
    public abstract void onEvent(Mediator mediator);
}

public class Alarm extends Colleague {

    @Override
    public void onEvent(Mediator mediator) {
        mediator.doEvent("alarm");
    }

    public void doAlarm() {
        System.out.println("doAlarm()");
    }
}

public class CoffeePot extends Colleague {

    @Override
    public void onEvent(Mediator mediator) {
        mediator.doEvent("coffeePot");
    }

    public void doCoffeePot() {
        System.out.println("doCoffeePot()");
    }
}

public class Calender extends Colleague {

    @Override
    public void onEvent(Mediator mediator) {
        mediator.doEvent("calender");
    }

    public void doCalender() {
        System.out.println("doCalender()");
    }
}

public class Sprinkler extends Colleague {

    @Override
    public void onEvent(Mediator mediator) {
        mediator.doEvent("sprinkler");
    }

    public void doSprinkler() {
        System.out.println("doSprinkler()");
    }
}

中介者集中处理各同事的事件:

public abstract class Mediator {
    public abstract void doEvent(String eventType);
}

public class ConcreteMediator extends Mediator {

    private Alarm alarm;
    private CoffeePot coffeePot;
    private Calender calender;
    private Sprinkler sprinkler;

    public ConcreteMediator(Alarm alarm, CoffeePot coffeePot, Calender calender, Sprinkler sprinkler) {
        this.alarm = alarm;
        this.coffeePot = coffeePot;
        this.calender = calender;
        this.sprinkler = sprinkler;
    }

    @Override
    public void doEvent(String eventType) {
        switch (eventType) {
            case "alarm":
                doAlarmEvent();
                break;
            case "coffeePot":
                doCoffeePotEvent();
                break;
            case "calender":
                doCalenderEvent();
                break;
            default:
                doSprinklerEvent();
        }
    }

    public void doAlarmEvent() {
        alarm.doAlarm();
        coffeePot.doCoffeePot();
        calender.doCalender();
        sprinkler.doSprinkler();
    }

    public void doCoffeePotEvent() {
        // ...
    }

    public void doCalenderEvent() {
        // ...
    }

    public void doSprinklerEvent() {
        // ...
    }
}
public class Client {

    public static void main(String[] args) {
        Alarm alarm = new Alarm();
        CoffeePot coffeePot = new CoffeePot();
        Calender calender = new Calender();
        Sprinkler sprinkler = new Sprinkler();
        Mediator mediator = new ConcreteMediator(alarm, coffeePot, calender, sprinkler);
        // 闹钟事件到达,调用中介者就可以操作相关对象
        alarm.onEvent(mediator);
    }
}

输出:

doAlarm()
doCoffeePot()
doCalender()
doSprinkler()

JDK 中的应用

  • All scheduleXXX() methods of java.util.Timer
  • java.util.concurrent.Executor#execute()
  • submit() and invokeXXX() methods of java.util.concurrent.ExecutorService
  • scheduleXXX() methods of java.util.concurrent.ScheduledExecutorService
  • java.lang.reflect.Method#invoke()

相关模式:与观察者的对比

中介者与观察者都在处理对象之间的通信:观察者通过发布-订阅,把主题的状态变化单向广播给多个观察者,是”一对多”的依赖;中介者则把同事对象之间的双向交互集中到中介对象中,把网状依赖变成星形。一对多的状态通知场景适合观察者,多个对象之间互相协调的场景适合中介者。

系列导航

← Angular 22+ 教程 20:Change Detection、OnPush 默认与 Zoneless 目录 软件工程 020:Twitter Java Style Guide →
← 返回文章列表