Что такое паттерн Chain of Responsibility
Что проверяют
Знаете ли вы паттерн не по учебнику, а по тому, чем уже пользуетесь: цепочка фильтров сервлетов, цепочка фильтров безопасности, перехватчики HTTP-клиента. Ждут объяснения роли звена и условия остановки, а не пересказа определения из справочника.
Как отвечать
Запрос передаётся по цепочке обработчиков, каждое звено решает: обработать самому, дополнить и передать дальше или прервать. Отправитель не знает получателя, состав и порядок задаются при сборке цепочки.
public interface Handler {
Decision handle(Request request);
}
public class LimitHandler implements Handler {
private final Handler next;
public LimitHandler(Handler next) {
this.next = next;
}
@Override
public Decision handle(Request request) {
if (request.amount().compareTo(request.limit()) > 0) {
return Decision.reject();
}
return next.handle(request);
}
}Ссылка на следующего передаётся в конструкторе, а хвостом ставится звено по умолчанию, которое всегда возвращает решение. Тогда ветка с пустой ссылкой не нужна, а цепочка собирается в одном месте конфигурации.
В Java паттерн нагляднее всего в фильтрах сервлетов, где звено само вызывает продолжение цепочки, и в фильтрах безопасности: аутентификация, проверка прав, ограничение частоты идут по порядку, и любое звено вправе ответить отказом.
Где спотыкаются
Не различают цепочку и декоратор. Декоратор всегда делегирует дальше, звено цепочки вправе остановить обработку, и про это отличие спрашивают следующим вопросом почти всегда.
Теряют запрос. Последнее звено ничего не возвращает и никому не передаёт, вызывающий получает пустоту без объяснения. Нужен либо замыкающий обработчик, либо явный ответ о том, что никто не взялся за запрос.
Делают звенья зависимыми от порядка неявно. Если проверка прав работает только после того, как предыдущее звено положило пользователя в контекст, перестановка ломает логику молча. Такие зависимости описываются явно, а порядок закрывается тестом.