Sobes.tech
Back to questions
Middle+
144
questionbank

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

Sobes Copilot

Get answers in real time

Answer from AI

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)