Что такое паттерн Медиатор?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое паттерн Медиатор?
Медиатор (Mediator) — это поведенческий паттерн проектирования, который централизует сложную коммуникацию между множеством объектов. Вместо того чтобы объекты общались друг с другом напрямую, они взаимодействуют только через медиатора.
Основная идея
Представьте аэропорт. Вместо того чтобы самолёты напрямую связывались друг с другом и диспетчерской вышкой, все коммуникации идут только через диспетчера (медиатора). Это предотвращает хаос и упрощает управление.
Проблема, которую решает Медиатор
Без паттерна — множество прямых связей (spaghetti code):
class Dialog:
def __init__(self):
self.button = Button()
self.checkbox = Checkbox()
self.textbox = Textbox()
# Каждый компонент должен знать о других
self.button.on_click = lambda: self._handle_button_click()
self.checkbox.on_change = lambda: self._handle_checkbox_change()
self.textbox.on_change = lambda: self._handle_textbox_change()
def _handle_button_click(self):
if self.checkbox.is_checked:
self.textbox.enable()
else:
self.textbox.disable()
def _handle_checkbox_change(self):
if self.checkbox.is_checked:
self.button.enable()
else:
self.button.disable()
def _handle_textbox_change(self):
# Более сложная логика взаимодействия
pass
С паттерном — централизованная коммуникация через медиатора.
Реализация паттерна Медиатор
from abc import ABC, abstractmethod
# Абстрактный Медиатор
class Mediator(ABC):
@abstractmethod
def notify(self, sender, event):
pass
# Компоненты (Collegue'и)
class Component:
def __init__(self, mediator: Mediator):
self._mediator = mediator
def emit_event(self, event):
"""Отправить событие медиатору"""
self._mediator.notify(self, event)
class Button(Component):
def click(self):
self.emit_event('button_clicked')
class Checkbox(Component):
def __init__(self, mediator: Mediator):
super().__init__(mediator)
self.is_checked = False
def toggle(self):
self.is_checked = not self.is_checked
self.emit_event('checkbox_toggled')
class Textbox(Component):
def __init__(self, mediator: Mediator):
super().__init__(mediator)
self.enabled = True
def set_enabled(self, enabled):
self.enabled = enabled
print(f"Textbox {'enabled' if enabled else 'disabled'}")
# Конкретный Медиатор
class DialogMediator(Mediator):
def __init__(self):
self.button = Button(self)
self.checkbox = Checkbox(self)
self.textbox = Textbox(self)
def notify(self, sender, event):
"""Обработать событие от компонента"""
if sender == self.button and event == 'button_clicked':
self._on_button_click()
elif sender == self.checkbox and event == 'checkbox_toggled':
self._on_checkbox_toggle()
def _on_button_click(self):
if self.checkbox.is_checked:
self.textbox.set_enabled(True)
else:
print("Нельзя включить textbox, если checkbox не отмечен")
def _on_checkbox_toggle(self):
if self.checkbox.is_checked:
self.button.enable()
else:
self.button.disable()
# Использование
mediator = DialogMediator()
mediator.checkbox.toggle() # checkbox теперь true
mediator.button.click() # Включит textbox
mediator.checkbox.toggle() # checkbox теперь false
mediator.button.click() # Не включит textbox
Реальный пример: система управления рейсами
from typing import List
from enum import Enum
class FlightStatus(Enum):
WAITING = "waiting"
BOARDING = "boarding"
TAXIING = "taxiing"
FLYING = "flying"
LANDED = "landed"
class AirportMediator:
"""Диспетчер аэропорта (Медиатор)"""
def __init__(self):
self.flights: List['Flight'] = []
self.gates: List['Gate'] = []
def register_flight(self, flight: 'Flight'):
self.flights.append(flight)
flight.mediator = self
def request_gate(self, flight: 'Flight') -> bool:
"""Выделить ворота для самолёта"""
available_gate = next(
(gate for gate in self.gates if not gate.is_occupied),
None
)
if available_gate:
available_gate.assign_flight(flight)
print(f"Ворота {available_gate.number} назначены рейсу {flight.number}")
return True
print(f"Свободных ворот нет для рейса {flight.number}")
return False
def notify_flight_status(self, flight: 'Flight', status: FlightStatus):
"""Обработать изменение статуса рейса"""
print(f"Рейс {flight.number}: {status.value}")
if status == FlightStatus.BOARDING:
self.request_gate(flight)
elif status == FlightStatus.LANDED:
# Освободить ворота
for gate in self.gates:
if gate.flight == flight:
gate.release()
print(f"Ворота {gate.number} освобождены")
class Flight:
def __init__(self, number: str, mediator: AirportMediator):
self.number = number
self.mediator = mediator
self._status = FlightStatus.WAITING
@property
def status(self):
return self._status
@status.setter
def status(self, new_status: FlightStatus):
self._status = new_status
self.mediator.notify_flight_status(self, new_status)
class Gate:
def __init__(self, number: int):
self.number = number
self.flight: Flight = None
self.is_occupied = False
def assign_flight(self, flight: Flight):
self.flight = flight
self.is_occupied = True
def release(self):
self.flight = None
self.is_occupied = False
# Использование
mediator = AirportMediator()
mediator.gates = [Gate(1), Gate(2), Gate(3)]
flight1 = Flight("AA100", mediator)
flight2 = Flight("BA200", mediator)
flight1.status = FlightStatus.BOARDING # Запросит ворота
flight2.status = FlightStatus.BOARDING # Запросит другие ворота
flight1.status = FlightStatus.LANDED # Освободит ворота
Реальный пример: чат-комната
from datetime import datetime
class ChatRoom:
"""Медиатор — чат-комната"""
def __init__(self, name: str):
self.name = name
self.users: List['User'] = []
def add_user(self, user: 'User'):
self.users.append(user)
self.broadcast(f"{user.name} присоединился", system=True)
def remove_user(self, user: 'User'):
self.users.remove(user)
self.broadcast(f"{user.name} покинул комнату", system=True)
def send_message(self, sender: 'User', message: str):
timestamp = datetime.now().strftime("%H:%M")
print(f"[{timestamp}] {sender.name}: {message}")
def broadcast(self, message: str, system=False):
prefix = "[СИСТЕМА]" if system else ""
print(f"{prefix} {message}")
class User:
def __init__(self, name: str, chat_room: ChatRoom):
self.name = name
self.chat_room = chat_room
def join(self):
self.chat_room.add_user(self)
def leave(self):
self.chat_room.remove_user(self)
def send(self, message: str):
self.chat_room.send_message(self, message)
# Использование
room = ChatRoom("General")
alice = User("Alice", room)
bob = User("Bob", room)
alice.join()
bob.join()
alice.send("Привет, Боб!")
bob.send("Привет, Алиса!")
alice.leave()
Медиатор vs Observer
Observer: объекты уведомляют подписчиков об изменениях Медиатор: объекты отправляют события медиатору, а он решает, что делать
# Observer — push уведомления
button.on_click.subscribe(lambda: textbox.enable())
# Медиатор — события через центр
button.click() # -> Медиатор.notify() -> принимает решение
Преимущества и недостатки
✅ Преимущества:
- Упрощает коммуникацию между объектами
- Централизует логику взаимодействия
- Легче тестировать компоненты отдельно
- Снижает coupling между объектами
❌ Недостатки:
- Медиатор может стать God Object (слишком большой)
- Сложнее отследить в debugger'е
- Сам медиатор становится критически важным
Когда использовать
- Диалоги и формы с множественным взаимодействием
- Системы управления (аэропорты, больницы)
- Чат-приложения
- Game event systems
- Orchestra conductor pattern (дирижёр оркестра)
Заключение
Медиатор — это паттерн для:
- Упрощения сложных коммуникаций
- Централизации логики взаимодействия
- Снижения связанности между объектами
- Контроля порядка и типа взаимодействия
Используй его, когда у тебя много объектов, которые нужно координировать.