Published: 14 November 2017
Tagged: Pattern iOS Swift
Необходимо последовательно выполнить провероку над данными, а затем для них применить изменения. Причем порядок проверок и изменений хочется применять как угодно, в зависимости от ситуации. В этом нам на помощь приходит поведенческий паттерн «Цепочка обязанностей».
Например нам надо проверить строку с телефонным номером и отформатировать ее. Опишем по порядку какие действия мы хотим выполнить:
- Строка не должна быть пустой и не nil
- Строка должна содержать определенное количество символов
- Необходимо отформатировать строку с учетом указанного формата
Цепочка обязанностей — это поведенческий паттерн проектирования, который позволяет передавать запросы последовательно по цепочке обработчиков. Каждый последующий обработчик решает, может ли он обработать запрос сам и стоит ли передавать запрос дальше по цепи.
Playground с примером на Git-Hub
Реализация
- Общий интерфейс для всех обработчиков MiddlewareProtocol:
- Добавим перечисление MiddlewareItem -- этот тип данных содержит само значение .value и ошибку .error если мы не прошли валидацию:
- Базовая реализация обработчика MiddlewareProtocol:
Все обработчики необходимо наследовать от Middleware
Теперь напишем конкретные обработчики для валидации и изменения данных, в нашем случае это строка:
- Обработчик проверки на nil и пустую строку: CheckNilMiddleware
- Обработчик проверки на длинну строки: CheckCountMiddleware
- Обработчик который форматирует строку с учетом указанного формата: PhoneFormatterMiddleware
Реализация всех трех классов описаных выше
Разберем подробнее
- Обработчик должен наследоваться от Middleware
- Перегружем метод check(value: MiddlewareItem) -> MiddlewareItem и описываем логику проверок, изменений над данными .value(let val).
- Если все успешно вызываем следующую проверку в нашем списке цепочек return checkNext(value: value)
- Если хотим прервать выполнение то сразу возвращаем ошибку return .error(“Example error text”).
- Если хотим подменить данные то передаем новое значение return checkNext(value: .value(“New value”))
Смотри комментарии к коду 👆
Использование
Проверяем и отформатируем телефонный номер с помощью нашей реализации:
Можно добавить немного функциональной магии, добавим оператор |>
Результатом выполнения будет вывод в консоль: +7 (963) 448 02-09
В заключении
Таким образом мы можем добавлять сколько угодно не зависящих друг от друга обработчиков и использовать их в зависимости от ситуации.
Где еще можно использовать:
- Редактор изображений. Добавить обработчики которые будут выполнять манипуляции над изображением, таким образом получим удобный способ применять фильтры
- Валидация при авторизации или регистрации пользователя