Что такое модель цепочки ответственности?

«С помощью шаблона« Цепочка ответственности »вы можете создать цепочку объектов, которые проверяют запрос. Каждый объект по очереди проверяет запрос и обрабатывает его или передает следующему объекту в цепочке ». - Head First Design Patterns, Эрик Фриман и Элизабет Фриман

Существует так много похожих объяснений, большинство из которых говорит что-то вроде: «позволяет разделить отправителя и получателя запроса».

Проще говоря, когда у вас есть список операций, которые должны быть выполнены в определенном порядке, где ввод каждой операции зависит от вывода предыдущей операции, это сценарий, в котором применим этот шаблон!

Пример:

Предположим, вы обращаетесь в службу поддержки клиентов за технической поддержкой. При этом задействованы следующие действия:

1) Вы слушаете автоматический голос и набираете несколько номеров, которые перенаправляют на заинтересованное лицо
2) Вы разговариваете с оператором, и он / она предлагает несколько решений
3) Вы пробуете их, и если это не работает оператор перенаправляет вас на следующий уровень иерархии для получения помощи
4) Снова вы получите несколько разных предложений от помощи уровня 2, и если они не сработают, вас перенаправят на более высокие уровни пока ваш запрос не будет решен

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

Лучший пример доступен здесь: refactoring.guru

Зачем нужна проверка формы?

Когда у нас есть HTML-форма с несколькими полями ввода, требующими определенных проверок, нам придется написать несколько операторов if-else, которые проверят их все. Здесь проверка выполняется одна за другой для каждого обязательного поля ввода, и если какой-либо из введенных данных недействителен, нам не нужно проверять оставшиеся! Таким образом, эти проверки выполняются последовательно и основаны на результате предыдущей проверки! Следовательно, этот сценарий является кандидатом на использование шаблона «Цепочка ответственности».

Форма, которую я должен был подтвердить

(Пожалуйста, исключите здесь пользовательский интерфейс! Я знаю, что UX можно улучшить, показывая все ошибки, связанные с вводом, встроенными рядом с соответствующим полем ввода, вместо того, чтобы показывать одну строку с ошибкой вверху. Но это было именно то, требование, которое у меня было в одном из моих проектов!)

Предположим, что это объект данных всплывающего окна, и каждый ключ в этом объекте каким-то образом привязан к полю ввода в пользовательском интерфейсе.

Итак, это объект данных, который необходимо проверить.

Проверка формы - перед применением этого шаблона:

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

  • Одна функция со слишком большим количеством операторов if / else нарушает «принцип единой ответственности», поскольку эта функция просто выполняет «слишком» много вещей!
  • Хотя код выглядит несколько читабельным, в будущем, если нам придется добавлять новые поля ввода, нам нужно будет добавить больше проверок к этой функции, которая со временем станет больше.
  • Кроме того, если в приложении есть какое-то другое место, которое также требует подмножества этих правил проверки, тогда нам придется скопировать и вставить пару строк, что приведет к дублированию кода.

Проверка с применением этого шаблона:

Итак, чтобы реализовать этот шаблон для проверки, нам сначала нужно определить базовый класс Validator. Это будет тип элемента в цепочке.

Для всех необходимых нам правил проверки давайте определим классы, которые наследуют этот базовый класс.

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

Объединив все эти классы вместе, мы создадим ValidatorService, который запускает цепочку проверки.

Несмотря на то, что появилось так много крошечных новых классов, код теперь стал более читаемым, и одна большая функция, в которой было слишком много операторов if-else, теперь преобразована в несколько крошечных, и каждая функция выполняет ровно одну вещь!
И если есть необходимость добавить дополнительные проверки, мы можем просто добавить соответствующие классы в цепочку. Более того, мы можем добавлять или удалять правила проверки во время выполнения.

[ОБНОВИТЬ]:

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

Вот реализация:

Вот и все

«Дизайн, который не принимает во внимание изменения, может привести к серьезному изменению дизайна в будущем». - Эрих Гамма, Шаблоны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования

Этот шаблон может быть немного излишним для простых проверок. Но для сложных проверок формы или если в будущем ожидается добавление дополнительных проверок, это поможет в поддержании кода, поскольку каждое правило является модульным и слабо связано с другими правилами и клиентом.

НО… Требуется ли этот шаблон в данном сценарии?

Или есть другой лучший способ проверки форм?

Прокомментируйте, пожалуйста, свои мысли по этому поводу! Жду возможности импровизировать!