Autumn SALE
Цепочка обязанностей

Цепочка обязанностей на Python

Цепочка обязанностей — это поведенческий паттерн, позволяющий передавать запрос по цепочке потенциальных обработчиков, пока один из них не обработает запрос.

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

Сложность:

Популярность:

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

Признаки применения паттерна: Цепочку обязанностей можно определить по спискам обработчиков или проверок, через которые пропускаются запросы. Особенно если порядок следования обработчиков важен.

Концептуальный пример

Этот пример показывает структуру паттерна Цепочка обязанностей, а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.

main.py: Пример структуры паттерна

from __future__ import annotations from abc import ABC, abstractmethod from typing import Any, Optional class Handler(ABC): """ Интерфейс Обработчика объявляет метод построения цепочки обработчиков. Он также объявляет метод для выполнения запроса. """ @abstractmethod def set_next(self, handler: Handler) -> Handler: pass @abstractmethod def handle(self, request) -> Optional[str]: pass class AbstractHandler(Handler): """ Поведение цепочки по умолчанию может быть реализовано внутри базового класса обработчика. """ _next_handler: Handler = None def set_next(self, handler: Handler) -> Handler: self._next_handler = handler # Возврат обработчика отсюда позволит связать обработчики простым # способом, вот так: # monkey.set_next(squirrel).set_next(dog) return handler @abstractmethod def handle(self, request: Any) -> str: if self._next_handler: return self._next_handler.handle(request) return None """ Все Конкретные Обработчики либо обрабатывают запрос, либо передают его следующему обработчику в цепочке. """ class MonkeyHandler(AbstractHandler): def handle(self, request: Any) -> str: if request == "Banana": return f"Monkey: I'll eat the {request}" else: return super().handle(request) class SquirrelHandler(AbstractHandler): def handle(self, request: Any) -> str: if request == "Nut": return f"Squirrel: I'll eat the {request}" else: return super().handle(request) class DogHandler(AbstractHandler): def handle(self, request: Any) -> str: if request == "MeatBall": return f"Dog: I'll eat the {request}" else: return super().handle(request) def client_code(handler: Handler) -> None: """ Обычно клиентский код приспособлен для работы с единственным обработчиком. В большинстве случаев клиенту даже неизвестно, что этот обработчик является частью цепочки. """ for food in ["Nut", "Banana", "Cup of coffee"]: print(f"\nClient: Who wants a {food}?") result = handler.handle(food) if result: print(f" {result}", end="") else: print(f" {food} was left untouched.", end="") if __name__ == "__main__": monkey = MonkeyHandler() squirrel = SquirrelHandler() dog = DogHandler() monkey.set_next(squirrel).set_next(dog) # Клиент должен иметь возможность отправлять запрос любому обработчику, а не # только первому в цепочке. print("Chain: Monkey > Squirrel > Dog") client_code(monkey) print("\n") print("Subchain: Squirrel > Dog") client_code(squirrel) 

Output.txt: Результат выполнения

Chain: Monkey > Squirrel > Dog Client: Who wants a Nut? Squirrel: I'll eat the Nut Client: Who wants a Banana? Monkey: I'll eat the Banana Client: Who wants a Cup of coffee? Cup of coffee was left untouched. Subchain: Squirrel > Dog Client: Who wants a Nut? Squirrel: I'll eat the Nut Client: Who wants a Banana? Banana was left untouched. Client: Who wants a Cup of coffee? Cup of coffee was left untouched. 

Цепочка обязанностей на других языках программирования

Цепочка обязанностей на C# Цепочка обязанностей на C++ Цепочка обязанностей на Go Цепочка обязанностей на Java Цепочка обязанностей на PHP Цепочка обязанностей на Ruby Цепочка обязанностей на Rust Цепочка обязанностей на Swift Цепочка обязанностей на TypeScript