Chain of Responsibility
Шаблон проектирования Chain of Responsibility («цепочка обязанностей») — один из поведенческих паттернов, предназначенный для организации обработки запросов таким образом, чтобы каждый объект мог либо обработать запрос самостоятельно, либо передать его следующему звену цепочки. Основная цель этого паттерна заключается в уменьшении зависимости между отправителем запроса и обработчиком запроса, делая систему более гибкой и расширяемой.
Основные элементы паттерна
- Handler: Абстрактный класс или интерфейс, определяющий метод обработки запроса (
handle()
). Реализует механизм передачи запроса следующему элементу цепи. - Concrete Handler: Конкретная реализация обработчика, способная обрабатывать определённые типы запросов. Если запрос не подходит, передаёт его дальше по цепочке.
- Client: Отправляет запросы в начало цепочки и ожидает результата.
Пример реализации на PHP
// Интерфейс обработчика
interface Handler {
public function setNext(Handler $handler): void;
public function handle($request): ?string;
}
abstract class AbstractHandler implements Handler {
private $nextHandler;
// Метод установки следующего обработчика в цепочке
public function setNext(Handler $handler): void {
$this->nextHandler = $handler;
}
// Основной метод обработки запроса
public function handle($request): ?string {
if ($this->canHandle($request)) {
return $this->processRequest($request);
}
if ($this->nextHandler !== null) {
return $this->nextHandler->handle($request); // Передача далее по цепочке
}
return null;
}
abstract protected function canHandle($request): bool;
abstract protected function processRequest($request): string;
}
class FirstHandler extends AbstractHandler {
protected function canHandle($request): bool {
return $request === 'first';
}
protected function processRequest($request): string {
return "First handler processed request";
}
}
class SecondHandler extends AbstractHandler {
protected function canHandle($request): bool {
return $request === 'second';
}
protected function processRequest($request): string {
return "Second handler processed request";
}
}
// Клиентская логика
$firstHandler = new FirstHandler();
$secondHandler = new SecondHandler();
$firstHandler->setNext($secondHandler);
echo $firstHandler->handle('first'); // Выведет: First handler processed request
echo "\n";
echo $firstHandler->handle('second'); // Выведет: Second handler processed request
Преимущества и недостатки
Преимущества:
- Уменьшение связи между клиентом и обработчиками, поскольку клиент взаимодействует только с первым элементом цепочки.
- Легкость добавления новых обработчиков путём расширения абстрактного класса.
- Возможность изменения порядка обработки запросов динамически во время выполнения программы.
Недостатки:
- Потеря контроля над передачей запроса вдоль всей цепочки, особенно при наличии большого количества элементов.
- Сложность отслеживания ошибок, если обработка выполняется несколькими элементами одновременно.
Таким образом, шаблон проектирования Chain of Responsibility полезен тогда, когда вам необходимо создать серию связанных объектов-обработчиков, позволяющих последовательно проверять условия и передавать обработку следующим объектам в цепочке.