Комментарии 8
У вас эти ifы спрятаны за setNext, если верно понимаю. И тогда в чём принципиальная разница, непонятно. Можно же этот маленький элемент логики записать ифами, и будет то же самое. А то, что вы продемонстрировали пример декомпозиции, — тоже типичный шаблон как будто из учебника
Как мне кажется, в таком подходе плюсом является тестируемость.
Если будет один метод и в нём много условных операторов, придётся тестировать много комбинаций входных данных для одного этого метода. Так очень легко просмотреть какой-то "edge case". Тут классы достаточно простые, написать тесты для них - легчайшее занятие.
Тестирование каждого обработчика по отдельности легко, но тестирование всей цепочки может стать трудоёмким из-за множества зависимостей между обработчиками. Так что тут как посмотреть!
Согласен, да и ситуации бывают разные, но в этом и подобных примерах мы можем предположить почти наверняка что если они работают правильно по отдельности, то будут работать правильно и в цепочке. В таком случае нам после тестирования всех хендлеров скорее важно что бы они вызывались в определённом порядке.
Ни одного котика в статье не обнаружено. Только очередной магазин. Предлагаю заголовок изменить на "...на примере магазина котиков". Хотя какая связь между котиками, магазином, и проверкой возраста всё ещё не ясно. Я надеюсь, у вас котики это не 18+ товар? Хотя котики это вообще не товар.
Что бы я добавил:
Финализировал бы методы в
AbstractHandler
Финализировал бы всех потомков
AbstractHandler
Естественно объявил бы тип для
$request
Добавил бы
Director
класс который собирал бы цепочку что бы не тянуть все эти зависимости в нужный класс тем самым захламляя конструктор. Но тут конечно по обстоятельствамТак же объявил
abstract HandlerException extends Exception
и его потомков для каждого хэндлера и, возможно, для каждого отдельного исключительного случая. Очень удобно, если класс исключения берёт на себя ответственность за создание сообщения, это разгружает бизнес логику.
Для паттерна Chain of Responsibility существуют частные случаи ("подпаттерны"), например: Chain, Pipeline, and Middleware.
Более детально можно прочитать в статье https://orangesoft.co/blog/chain-of-responsibility-design-pattern-in-php
а что мешает сделать интерфейс с одним методом handle как сейчас, сделать все реализации, накидать реализации в массив и проходить по массиву реализаций, вызывая $request = $handler->handle($request) , без каких либо setNext в хэндлере прям как в книге банды четырех?
Реализация паттерна Chain of Responsibility на примере котиков в PHP