Что такое паттерн Медиатор (Mediator)?

Ответ

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

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

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

Преимущества:

  • Уменьшение связанности: Компоненты становятся независимыми друг от друга.
  • Централизация управления: Вся логика взаимодействия находится в одном месте, что упрощает её анализ и изменение.
  • Упрощение повторного использования компонентов: Компоненты легче выносить в другие контексты, так как они не зависят от конкретных «коллег».

Недостатки:

  • Риск создания «Богатого объекта»: Медиатор может превратиться в монолитный класс, который знает и делает слишком много, нарушая принцип единственной ответственности.

Пример на C# (Упрощённая система диалога в чате):

// 1. Интерфейс Медиатора
public interface IChatMediator
{
    void SendMessage(string message, User sender);
    void RegisterUser(User user);
}

// 2. Конкретный Медиатор
public class ChatRoom : IChatMediator
{
    private List<User> _users = new List<User>();

    public void RegisterUser(User user)
    {
        _users.Add(user);
        user.Mediator = this; // Устанавливаем связь «пользователь -> медиатор»
    }

    public void SendMessage(string message, User sender)
    {
        // Медиатор решает, как обработать сообщение.
        // Здесь он рассылает его всем, кроме отправителя.
        foreach (var user in _users)
        {
            if (user != sender)
            {
                user.Receive(message, sender.Name);
            }
        }
        // Логику можно легко изменить: отправлять только адресату, фильтровать слова и т.д.
    }
}

// 3. Класс «Коллеги» (Colleague), который знает только о Медиаторе
public class User
{
    public string Name { get; }
    public IChatMediator Mediator { get; set; } // Ссылка на посредника

    public User(string name)
    {
        Name = name;
    }

    public void Send(string message)
    {
        Console.WriteLine($"{Name} отправляет: {message}");
        // Вместо прямого вызова других пользователей, сообщение отправляется медиатору.
        Mediator?.SendMessage(message, this);
    }

    public void Receive(string message, string senderName)
    {
        Console.WriteLine($"[{Name}] получил от {senderName}: {message}");
    }
}

// 4. Клиентский код
class Program
{
    static void Main()
    {
        // Создаём медиатор (чат-комнату)
        IChatMediator chatRoom = new ChatRoom();

        // Создаём пользователей
        User alice = new User("Alice");
        User bob = new User("Bob");
        User charlie = new User("Charlie");

        // Регистрируем пользователей в медиаторе
        chatRoom.RegisterUser(alice);
        chatRoom.RegisterUser(bob);
        chatRoom.RegisterUser(charlie);

        // Пользователи общаются через медиатор
        alice.Send("Привет всем!");
        // Вывод:
        // Alice отправляет: Привет всем!
        // [Bob] получил от Alice: Привет всем!
        // [Charlie] получил от Alice: Привет всем!

        bob.Send("Привет, Alice!");
        // Вывод:
        // Bob отправляет: Привет, Alice!
        // [Alice] получил от Bob: Привет, Alice!
        // [Charlie] получил от Bob: Привет, Alice!
    }
}

Ответ 18+ 🔞

Так, слушай, про медиатор, это ж классика, блядь! Представь себе бардак в коде, где у тебя десяток объектов друг на друга ссылаются, как мухи в банке, и один чихнул — все остальные начинают дергаться. Пиздец, а не поддержка.

Вот, например, у тебя интерфейс: кнопка, поле ввода, чекбокс. И они все друг другу должны сообщать: «я нажался», «я изменился», «я выключился». Если делать это напрямую, то получается такая паутина из зависимостей, что через месяц сам не поймешь, какой пидор на какого влияет. Изменяешь одну строчку — и всё, поехали танцы с бубном, пол-системы ломается. Ужас, блядь.

А медиатор — это как умный диспетчер на хуй. Он говорит: «Ребята, успокойтесь, ебать! Не дергайте друг друга напрямую. Все вопросы — ко мне». И каждый объект теперь знает только этого диспетчера. Хочешь что-то сказать миру? Кричи медиатору. А уж медиатор сам разберется, кому и что передать.

Плюсы, блядь, очевидные:

  • Связанность падает просто в ноль. Объекты становятся независимыми, как суверенные государства, блядь. Хочешь один выдернуть и использовать в другом месте? Да пожалуйста, хуле.
  • Вся ебля с коммуникацией теперь в одном месте, в этом самом медиаторе. Хочешь поменять логику, кто кого оповещает? Не надо рыскать по всему коду — идёшь в один класс и правишь там. Красота.
  • Переиспользовать компоненты — одно удовольствие. Они же ни о ком, кроме медиатора, не знают.

Но есть и подстава, конечно:

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

Смотри, как это на C# выглядит, на примере чата:

// 1. Интерфейс нашего диспетчера-медиатора
public interface IChatMediator
{
    void SendMessage(string message, User sender);
    void RegisterUser(User user);
}

// 2. Конкретная комната для болтовни, она же медиатор
public class ChatRoom : IChatMediator
{
    private List<User> _users = new List<User>();

    public void RegisterUser(User user)
    {
        _users.Add(user);
        user.Mediator = this; // Говорим юзеру: «Запомни, сынок, твой начальник — я»
    }

    public void SendMessage(string message, User sender)
    {
        // А вот тут медиатор рулит процессом. Решает, кому слать.
        // Сейчас он шлёт всем, кроме того, кто написал. Логику можешь менять как хочешь.
        foreach (var user in _users)
        {
            if (user != sender)
            {
                user.Receive(message, sender.Name);
            }
        }
    }
}

// 3. Юзер, который тупо знает про медиатора и всё
public class User
{
    public string Name { get; }
    public IChatMediator Mediator { get; set; } // Ссылка на главного

    public User(string name)
    {
        Name = name;
    }

    public void Send(string message)
    {
        Console.WriteLine($"{Name} отправляет: {message}");
        // Вместо того чтобы орать на каждого в отдельности, кричим медиатору
        Mediator?.SendMessage(message, this);
    }

    public void Receive(string message, string senderName)
    {
        Console.WriteLine($"[{Name}] получил от {senderName}: {message}");
    }
}

// 4. Ну и как это всё собирается
class Program
{
    static void Main()
    {
        // Создаём посредника — чат-рум
        IChatMediator chatRoom = new ChatRoom();

        // Лепим пользователей
        User alice = new User("Alice");
        User bob = new User("Bob");
        User charlie = new User("Charlie");

        // Прописываем всех в этом чате
        chatRoom.RegisterUser(alice);
        chatRoom.RegisterUser(bob);
        chatRoom.RegisterUser(charlie);

        // А теперь они общаются через одного дядю
        alice.Send("Привет всем!");
        // На экране:
        // Alice отправляет: Привет всем!
        // [Bob] получил от Alice: Привет всем!
        // [Charlie] получил от Alice: Привет всем!

        bob.Send("Привет, Alice!");
        // И так далее...
    }
}

Вот и вся магия, ёпта. Вместо того чтобы плодить связи между всеми подряд, ты заводишь одного ответственного за болтовню. И живёшь спокойно. Главное — не дай этому медиатору превратиться в монстра, который знает про твою личную жизнь больше, чем ты сам.