В чем заключается суть паттерна проектирования Медиатор (Mediator)

Ответ

Паттерн Медиатор (Mediator) — это поведенческий паттерн проектирования, который устраняет сильную связанность между объектами (компонентами), заставляя их взаимодействовать через центральный объект-посредник («медиатор»).

Проблема, которую решает: Когда в системе много компонентов, которые должны взаимодействовать друг с другом, это приводит к сложной сети прямых связей («спагетти-код»). Каждый компонент должен знать о многих других, что затрудняет его изменение и переиспользование.

Решение: Медиатор инкапсулирует всю логику взаимодействия. Компоненты больше не ссылаются друг на друга, а только на медиатор. Они отправляют уведомления медиатору, а он уже решает, кому их перенаправить.

Ключевые преимущества:

  • Слабая связанность (Low Coupling): Компоненты не зависят друг от друга.
  • Централизованное управление: Логика взаимодействия находится в одном месте.
  • Упрощение поддержки: Легче изменять поведение системы, модифицируя только медиатор.
  • Повышение переиспользуемости: Отдельные компоненты проще использовать в других контекстах.

Пример на Python:

from abc import ABC, abstractmethod

# Интерфейс Медиатора
class Mediator(ABC):
    @abstractmethod
    def notify(self, sender: object, event: str) -> None:
        pass

# Базовый Компонент
class BaseComponent:
    def __init__(self, mediator: Mediator = None):
        self._mediator = mediator

    @property
    def mediator(self) -> Mediator:
        return self._mediator

    @mediator.setter
    def mediator(self, mediator: Mediator) -> None:
        self._mediator = mediator

# Конкретные Компоненты
class ComponentA(BaseComponent):
    def do_work(self):
        print("Компонент A выполняет действие и уведомляет медиатора.")
        self.mediator.notify(self, "EventA")

class ComponentB(BaseComponent):
    def react_on_a(self):
        print("Компонент B реагирует на событие A.")

    def react_on_c(self):
        print("Компонент B реагирует на событие C.")

class ComponentC(BaseComponent):
    def do_another_work(self):
        print("Компонент C выполняет действие и уведомляет медиатора.")
        self.mediator.notify(self, "EventC")

# Конкретный Медиатор
class ConcreteMediator(Mediator):
    def __init__(self, component_a: ComponentA, component_b: ComponentB, component_c: ComponentC):
        self._component_a = component_a
        self._component_a.mediator = self
        self._component_b = component_b
        self._component_b.mediator = self
        self._component_c = component_c
        self._component_c.mediator = self

    def notify(self, sender: object, event: str) -> None:
        if event == "EventA":
            print("Медиатор получил событие от A и передает его B.")
            self._component_b.react_on_a()
        elif event == "EventC":
            print("Медиатор получил событие от C и передает его B.")
            self._component_b.react_on_c()

# Использование
c1 = ComponentA()
c2 = ComponentB()
c3 = ComponentC()

mediator = ConcreteMediator(c1, c2, c3)

c1.do_work()
print("-" * 20)
c3.do_another_work()

Ответ 18+ 🔞

О, паттерн Медиатор, ёпта! Это ж как раз про то, когда у тебя в проекте компоненты начинают друг друга знать настолько, что превращаются в одну большую, блядь, семью — где все друг другу троюродные племянники и постоянно звонят по любому поводу.

Суть проблемы, которую он решает, проще говоря: Представь, что у тебя есть три класса: Кнопка, Поле ввода и Список. И они все должны друг с другом общаться. Кнопка нажалась — надо Поле очистить и Список обновить. Поле изменилось — надо Кнопку заблокировать. В итоге ты пишешь в коде Кнопки вызовы методов и Поля, и Списка. Получается пиздец какой спагетти-код, где всё завязано на всё. Хули один компонент знает про внутренности другого? Это же пиздец как негибко! Захотел Список заменить на Таблицу — придётся во всех остальных классах ковыряться. Терпения ноль, ебать!

А решение-то какое, блядь? А решение — впендюрить между ними ещё одного чувака, Медиатора. Это такой центральный диспетчер, почтальон, ёбаный в рот. Теперь наши Кнопка, Поле и Список нихуя не знают друг о друге. Они знают только этого медиатора. Сделал что-то — крикнул медиатору: «Эй, я, Кнопка, только что нажался, событие такое-то!». А медиатор уже сам решает, кому и что передать: «Ага, Кнопка нажалась — значит, Поле, чисться, а Список, обновляйся, пидары!». Всё, связанность упала до плинтуса.

Что хорошего-то, спрашиваешь?

  • Слабая связанность, мать его. Компоненты становятся независимыми идиотами, которые только умеют своё дело делать и орать медиатору. Их теперь можно таскать в другие проекты, как чемоданы.
  • Вся хуйня в одном месте. Вся логика «кто кому что должен сказать» сидит в медиаторе. Захотел поменять поведение — идёшь в один класс, а не в двадцать.
  • Поддержка проще. Не надо рыться во всём коде, чтобы понять, почему Поле очищается при нажатии Кнопки. Всё написано в медиаторе, как на ладони.

А вот тебе пример на Python, чтобы совсем понятно стало. Блок кода не трогаю, он святой:

from abc import ABC, abstractmethod

# Интерфейс Медиатора
class Mediator(ABC):
    @abstractmethod
    def notify(self, sender: object, event: str) -> None:
        pass

# Базовый Компонент
class BaseComponent:
    def __init__(self, mediator: Mediator = None):
        self._mediator = mediator

    @property
    def mediator(self) -> Mediator:
        return self._mediator

    @mediator.setter
    def mediator(self, mediator: Mediator) -> None:
        self._mediator = mediator

# Конкретные Компоненты
class ComponentA(BaseComponent):
    def do_work(self):
        print("Компонент A выполняет действие и уведомляет медиатора.")
        self.mediator.notify(self, "EventA")

class ComponentB(BaseComponent):
    def react_on_a(self):
        print("Компонент B реагирует на событие A.")

    def react_on_c(self):
        print("Компонент B реагирует на событие C.")

class ComponentC(BaseComponent):
    def do_another_work(self):
        print("Компонент C выполняет действие и уведомляет медиатора.")
        self.mediator.notify(self, "EventC")

# Конкретный Медиатор
class ConcreteMediator(Mediator):
    def __init__(self, component_a: ComponentA, component_b: ComponentB, component_c: ComponentC):
        self._component_a = component_a
        self._component_a.mediator = self
        self._component_b = component_b
        self._component_b.mediator = self
        self._component_c = component_c
        self._component_c.mediator = self

    def notify(self, sender: object, event: str) -> None:
        if event == "EventA":
            print("Медиатор получил событие от A и передает его B.")
            self._component_b.react_on_a()
        elif event == "EventC":
            print("Медиатор получил событие от C и передает его B.")
            self._component_b.react_on_c()

# Использование
c1 = ComponentA()
c2 = ComponentB()
c3 = ComponentC()

mediator = ConcreteMediator(c1, c2, c3)

c1.do_work()
print("-" * 20)
c3.do_another_work()

Видишь, как оно работает? ComponentA делает своё дело и орёт медиатору. Медиатор, этот хитрая жопа, смотрит: «А, событие EventA — значит, надо ComponentB пнуть, чтобы он среагировал». И пиздык — ComponentB выполняет react_on_a(). Никаких прямых связей, один сплошной порядок, ебать мои старые костыли! Красота же.