Посредник

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

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

Когда использовать паттерн
  • Когда требуется организовать взаимодействие между множеством объектов, минимизируя прямые зависимости между ними.

  • Когда важно улучшить расширяемость системы и снизить сложность за счёт централизованного управления.

  • Когда система имеет сложные зависимости между объектами, и нужно избежать нагромождения ссылок между ними.
Основные участники паттерна
Mediator (Посредник) — интерфейс или класс, который определяет методы для управления взаимодействием между объектами.

ConcreteMediator (Конкретный посредник) — класс, который реализует логику взаимодействия между объектами.

Colleague (Коллеги) — классы, представляющие объекты, взаимодействующие через посредника. Они используют посредника для связи друг с другом.
Пример реализации паттерна
Рассмотрим пример чата, где пользователи могут обмениваться сообщениями. Вместо прямого взаимодействия между пользователями, сообщение проходит через посредника, который управляет отправкой и получением сообщений.
Шаг 1: Определяем интерфейс посредника
from abc import ABC, abstractmethod

class Mediator(ABC):
    @abstractmethod
    def send_message(self, message, sender):
        pass
Создадим интерфейс Mediator, который будет отвечать за передачу сообщений между пользователями.

Здесь метод send_message передаёт сообщение от одного пользователя к другим.
Шаг 2: Создаём класс конкретного посредника
class ChatMediator(Mediator):
    def __init__(self):
        self._users = []

    def add_user(self, user):
        self._users.append(user)

    def send_message(self, message, sender):
        for user in self._users:
            # Отправляем сообщение всем пользователям, кроме отправителя
            if user != sender:
                user.receive(message)
Класс ChatMediator реализует интерфейс Mediator и управляет пользователями, организуя их взаимодействие.

  • Метод add_user добавляет пользователя в список участников чата.
  • Метод send_message отправляет сообщение всем пользователям, кроме того, кто его отправил.
Шаг 3: Создаём класс пользователей (коллеги)
class User:
    def __init__(self, name, mediator):
        self.name = name
        self._mediator = mediator
        self._mediator.add_user(self)

    def send(self, message):
        print(f"{self.name} sends: {message}")
        self._mediator.send_message(message, self)

    def receive(self, message):
        print(f"{self.name} receives: {message}")
Каждый пользователь обращается к посреднику для отправки сообщений другим пользователям.

Метод send отправляет сообщение через посредника, который решает, кому его переслать.
Метод receive принимает сообщение и выводит его на экран.
Шаг 4: Использование паттерна
def main():
    mediator = ChatMediator()

    user1 = User("Alice", mediator)
    user2 = User("Bob", mediator)
    user3 = User("Charlie", mediator)

    user1.send("Hello, everyone!")
    user2.send("Hi, Alice!")
    user3.send("Hey, folks!")

main()
Результат выполнения
Alice sends: Hello, everyone!
Bob receives: Hello, everyone!
Charlie receives: Hello, everyone!
Bob sends: Hi, Alice!
Alice receives: Hi, Alice!
Charlie receives: Hi, Alice!
Charlie sends: Hey, folks!
Alice receives: Hey, folks!
Bob receives: Hey, folks!
Как работает код?
  • Создание посредника и пользователей. ChatMediator управляет всеми пользователями чата.

  • Отправка сообщений. Пользователь вызывает метод send для отправки сообщения. ChatMediator получает сообщение и отправляет его всем остальным пользователям.

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

  • Централизованное управление. Логика взаимодействия управляется посредником, что облегчает поддержку и изменение кода.

  • Упрощение структуры. Уменьшается количество зависимостей, что упрощает структуру системы.
Недостатки
  • Увеличение сложности посредника. Посредник может стать слишком большим и сложным, если количество взаимодействий возрастает.

  • Зависимость от посредника. Если посредник выходит из строя, вся система может прекратить работу.