Mediator Pattern — Посредник
Топология «звезда» вместо «все со всеми». Объекты не зацепляются напрямую — общаются через медиатор.
Проблема
N объектов, каждый должен общаться с каждым. Полный граф связей — N×(N-1)/2 связей. При N=10 это 45 связей. Сильное зацепление, изменение одного — каскад правок. Аналог в реальной жизни — авиадиспетчер.
Где используется
- Event bus / pub-sub системы в SPA
- Управление состоянием чата (кто кому пишет)
- Координация компонентов UI (модальные окна, уведомления)
- Архитектура микрофронтендов
- Redux и подобные state managers (store как медиатор)
Решение
- Все объекты ссылаются на медиатор, не друг на друга.
- Медиатор знает обо всех участниках и маршрутизирует сообщения.
- Связей становится N, а не N²/2.
- Объекты можно тестировать в изоляции (с моком медиатора).
Реализации
Базовый медиатор
class Mediator {
participants = new Map();
register(name, obj) {
this.participants.set(name, obj);
obj.mediator = this;
}
send(from, to, message) {
this.participants.get(to)?.receive(from, message);
}
}
class Component {
receive(from, message) { console.log(`from ${from}: ${message}`); }
send(to, message) { this.mediator.send(this.name, to, message); }
}
const med = new Mediator();
const a = new Component(); a.name = 'A';
const b = new Component(); b.name = 'B';
med.register('A', a);
med.register('B', b);
a.send('B', 'hi');
Pub/Sub стиль медиатора
class EventBus {
constructor { this.handlers = {}; }
subscribe(event, handler) {
if (!this.handlers[event]) this.handlers[event] = ;
this.handlers[event].push(handler);
return => {
this.handlers[event] = this.handlers[event].filter(h => h !== handler);
};
}
publish(event, data) {
(this.handlers[event] || ).forEach(h => h(data));
}
}
const bus = new EventBus();
const unsub = bus.subscribe('userLoggedIn', (user) => console.log(`Hi, ${user.name}`));
bus.publish('userLoggedIn', { name: 'Ivan' });
unsub;
Чат-комната
class ChatRoom {
constructor { this.participants = {}; }
register(participant) {
this.participants[participant.name] = participant;
participant.chatRoom = this;
}
send(message, from, to) {
if (to) {
this.participants[to]?.receive(message, from);
} else {
Object.values(this.participants).forEach(p => {
if (p.name !== from) p.receive(message, from);
});
}
}
}
class Participant {
constructor(name) { this.name = name; }
send(message, to) { this.chatRoom.send(message, this.name, to); }
receive(message, from) { console.log(`[${this.name}] ${from}: ${message}`); }
}
Где используется в JS-экосистеме
- Redux store — центральный медиатор между компонентами
- Event bus в Vue/React (
mitt,eventemitter3) - NestJS @EventEmitter + handlers — медиаторная топология
- Chat-app server — клиенты не знают друг о друге, общаются через сервер
- Air traffic control — классический пример из книги GoF
Подводные камни
- Mediator → God Object: если медиатор знает всё про всех, становится монстром. Медиатор должен только координировать, не обрабатывать логику.
- Mediator vs Observer: Mediator знает участников; Observable рассылает всем подписчикам, не знающим друг друга.
- Mediator vs Bridge: Bridge связывает иерархии наследования; Mediator связывает объекты без знания об иерархиях.
- Mediator vs Facade: Facade скрывает сложность подсистемы наружу; Mediator связывает объекты между собой внутри.
- Утечки памяти при подписке — если не отписываться при уничтожении компонента, обработчики накапливаются.
- Слишком много событий — избыточное количество делает систему трудно отслеживаемой. Используй namespace:
'cart:add','cart:remove'.
Главные тезисы автора
- «Функцию зацепления переносим на медиатор» — суть паттерна.
- «Объекты не зацеплены друг за друга. Медиатор сам их зацепляет».
- Топология меняется с полного графа на звезду.
- Композиция или агрегация в медиаторе — оба валидны.
- Bridge vs Mediator: Bridge знает об иерархиях, Mediator — нет.
- На функциональном уровне — это функция, связывающая два контракта.
🎓 Источники
- 🎓 Как применять паттерны на примере Mediator и Bridge · 2025-02-01
- Mediator инкапсулирует взаимодействие
- Зацепление переносим на медиатор
- Композиция/агрегация в медиаторе
- Bridge vs Mediator
- 🎓 GoF Patterns Обзор всех паттернов · 2025-04-29
- Топология «звезда»: N связей вместо N²/2
- refactoring.guru — Mediator