Почему цепочка ответственности неуместна, если для каждого запроса есть только один обработчик?

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

В моем приложении всегда будет ровно один обработчик для каждого запроса, полученного от хоста. Таким образом, я заранее настроил свою цепочку обработчиков, и цикл начинается с ожидания запроса от хоста. Запрос передается «корневому» обработчику, который, изучив часть запроса, решает, обрабатывать ли его или передать дальше по цепочке. Как только запрос обработан, мы возвращаемся к ожиданию другого запроса от хоста.

Опять же, только один обработчик будет обрабатывать запрос. Необработанный запрос, т. е. прохождение всей цепочки обработчиков, является состоянием ошибки.

После прочтения о шаблоне цепочки ответственности на сайте www.sourcemaking.com эта цитата привлекла мое внимание ( последний абзац в разделе «Обсуждение»):

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

Есть ли веская практическая причина, почему это так? Мне кажется, что использование Chain of Responsibility в случае, против которого предостерегает автор, вполне правомерно. Может ли кто-нибудь дать мне некоторое представление о том, почему это был бы плохой выбор дизайна?


person amandion    schedule 24.01.2017    source источник


Ответы (1)


Я думаю, что предупреждение, которое вы процитировали, было сформулировано плохо и могло вызвать некоторую путаницу. Я думаю, что автор хотел сказать:

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

Другой способ сказать это состоит в том, что шаблон цепочки ответственности вносит некоторую сложность, и вы должны использовать эту сложность только в том случае, если у вас действительно есть несколько обработчиков, и если клиентскому объекту нелегко узнать, какой обработчик использовать. Если вы знаете, что у вас есть только один обработчик, нет необходимости в цепочке или указателе, потому что вы точно знаете, какому объекту передать запрос. Если у вас есть несколько обработчиков, но легко посмотреть на запрос и сказать, какой объект будет его обрабатывать, используя простые операторы «если», то вам снова не нужна цепочка или указатель.

В сторону: как человек, внедривший прошивку USB на несколько платформ, я не думаю, что вам нужно что-то настолько формальное, как цепочка ответственности. Я также думаю, что вам даже не нужны указатели. Вы можете использовать простые операторы if и жестко запрограммированные обратные вызовы из стека USB в пользовательский код, чтобы направлять каждую входящую передачу управления соответствующему коду, который может ее обработать.

person David Grayson    schedule 24.01.2017
comment
Ах, да, это имеет смысл. @DavidGrayson, вы можете использовать простые операторы if и жестко запрограммированные обратные вызовы из стека USB в пользовательский код, чтобы направлять каждую входящую передачу управления соответствующему коду, который может ее обработать. Можете ли вы уточнить, что вы имеете в виду здесь? - person amandion; 25.01.2017
comment
Вы можете посмотреть на этот стек USB и посмотрите, как при запуске новой передачи управления он вызывает либо usbStandardDeviceRequestHandler, либо usbCallbackSetupHandler в зависимости от значений в передаче управления. Последняя функция должна быть определена в любом приложении, использующем стек USB. - person David Grayson; 25.01.2017
comment
спасибо за ссылку! Я видел подобные примеры от производителя платформы, которую мы используем. Однако у меня есть требования, которые требуют гибкости во время выполнения в отношении того, как и когда обрабатываются запросы. Это была одна из причин, по которой я пошел с CoR. Еще раз спасибо за ваш вклад! - person amandion; 25.01.2017