Паттерн «Цепочка ответственности» (Chain of Responsibility) — это поведенческий паттерн проектирования, который позволяет передавать запросы последовательно по цепочке обработчиков. Каждый обработчик решает, может ли он обработать запрос, или его нужно передать следующему звену цепи. Паттерн полезен в сценариях, где система должна выполнять разнородные проверки или операции над объектом, сохраняя гибкость и минимальную связность между компонентами.
Проблема
Представьте, что вы разрабатываете систему обработки HTTP-запросов, где каждый запрос требует выполнения нескольких этапов проверки:
1. Аутентификация пользователя.
2. Проверка прав доступа.
3. Валидация данных.
4. Логирование действий.
Если реализовать все этапы в одном классе, код станет монолитным и сложным для изменения. Добавление новых проверок или изменение порядка их выполнения потребует переписывания логики, что нарушает принцип открытости/закрытости (Open/Closed Principle).
Решение: паттерн Chain of Responsibility
Паттерн предлагает разбить обработку на отдельные объекты-обработчики (Handlers), связанные в цепочку. Каждый обработчик:
- Решает, может ли он обработать запрос.
- Либо передает запрос следующему обработчику в цепочке.
Таким образом, запрос проходит через все звенья цепи, пока не будет обработан или не достигнет ее конца.
Структура паттерна:
1. Handler — интерфейс обработчика с методом `handle()` и ссылкой на следующий обработчик.
2. ConcreteHandler — конкретные реализации обработчиков.
3. Client — инициализирует цепочку и запускает обработку.
Пример реализации на Python
Рассмотрим систему проверки доступа к документу, где каждый этап проверки реализован как отдельный обработчик.
Преимущества и недостатки
Плюсы:
- Уменьшает зависимость между клиентом и обработчиками.
- Позволяет динамически менять цепочку или добавлять новые обработчики.
- Реализует принцип единственной ответственности (Single Responsibility Principle).
Минусы:
- Нет гарантии, что запрос будет обработан (если цепочка не завершена).
- Может усложнить отладку из-за распределенной логики.
Когда использовать?
- Обработка событий в GUI, где событие передается по цепочке виджетов.
- Middleware в веб-фреймворках (например, Django, Flask).
- Проверка прав доступа или многоэтапная валидация данных.
- Логирование с разными уровнями детализации (info, warning, error).
Модификации
- Прерывание цепи: Обработчик может прервать цепочку, если запрос обработан.
- Обработка несколькими обработчиками: Например, уведомление всех подписчиков события.
- Рекурсивные цепи: Обработчики могут вызывать сами себя для сложных сценариев.
Заключение
Паттерн Chain of Responsibility идеально подходит для систем, где запросы должны проходить через серию независимых проверок или преобразований. В Python его легко реализовать через ссылки на следующий обработчик в каждом классе. Используйте этот паттерн, чтобы сделать код гибким, расширяемым и соответствующим принципам SOLID.