Sobes.tech
Назад к вопросам
Middle+
145
questionbank

Что такое цепочка ответственности (Chain of Responsibility)?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

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

  • Назначение: Деcoupling (слабая связанность) отправителя запроса от получателя.
  • Принцип работы: Создается linked list объектов-обработчиков. Запрос поступает первому обработчику. Если он не может обработать запрос, он передает его следующему, и так до конца цепочки.
  • Компоненты:
    • Handler (Обработчик): Интерфейс или абстрактный класс, определяющий метод обработки запроса (handle()) и опционально метод установки следующего обработчика (set_next()).
    • ConcreteHandler (Конкретный Обработчик): Классы, реализующие интерфейс Handler и содержащие логику обработки конкретного типа запроса.
    • Client (Клиент): Объект, создающий запрос и отправляющий его первому обработчику в цепочке.
  • Преимущества:
    • Снижение связанности между отправителем и получателем.
    • Гибкость в добавлении или изменении обработчиков.
    • Возможность динамически изменять порядок обработчиков в цепочке.
  • Недостатки:
    • Запрос может не быть обработан, если ни один обработчик в цепочке не подходит.
    • Отладка может быть затруднена из-за потенциально сложного потока выполнения.
  • Примеры использования:
    • Обработка событий в UI-фреймворках.
    • Системы логирования с различными уровнями детализации.
    • Обработка запросов в веб-фреймворках (middleware).
    • Системы аутентификации и авторизации.
// Пример структуры
class Handler:
    def set_next(self, handler):
        pass

    def handle(self, request):
        pass

class AbstractHandler(Handler):
    _next_handler = None

    def set_next(self, handler):
        self._next_handler = handler
        return handler # Позволяет строить цепочку

    def handle(self, request):
        if self._next_handler:
            return self._next_handler.handle(request)
        return None # Запрос не обработан

class ConcreteHandlerA(AbstractHandler):
    def handle(self, request):
        if request == "A":
            return f"ConcreteHandlerA handled {request}"
        else:
            return super().handle(request)

class ConcreteHandlerB(AbstractHandler):
    def handle(self, request):
        if request == "B":
            return f"ConcreteHandlerB handled {request}"
        else:
            return super().handle(request)

// Клиентский код
# Создаем цепочку
handler_a = ConcreteHandlerA()
handler_b = ConcreteHandlerB()

handler_a.set_next(handler_b)

# Отправляем запрос
request_a = "A"
result_a = handler_a.handle(request_a)
print(result_a)

request_b = "B"
result_b = handler_a.handle(request_b)
print(result_b)

request_c = "C" # Не будет обработан
result_c = handler_a.handle(request_c)
print(result_c)