
Вы просмотрели бесчисленные учебные пособия, использующие операторы If-else. Вы, вероятно, также читали книги по программированию, пропагандирующие использование If-else в качестве фактического метода ветвления.
Возможно, это даже ваш режим по умолчанию, чтобы использовать If-else. Но давайте покончим с этим прямо сейчас, заменив If-else объектами состояния.
Обратите внимание, что этот подход можно использовать, если вы пишете класс с методами, которые нуждаются в изменении его реализаций в зависимости от текущего состояния. Вы бы применили другой подход, если бы не имели дело с изменяющимся состоянием объекта.
Даже если вы слышали о шаблоне состояния, вы можете задаться вопросом, как он реализован в готовом к продакшену коде.
Для тех, кто все еще находится в неведении, вот очень краткое введение.
Вы увеличите сложность с любым новым условным требованием, реализованным с помощью If-else.
Применяя шаблон состояния, вы просто изменяете поведение объектов, используя специализированные объекты состояния вместо операторов If-else.
Прошли те дни, когда код выглядел примерно так, как показано ниже.

Вы, конечно, писали более сложные ветвления раньше. Несколько лет назад я был уверен в этом.
Приведенная выше логика ветвления даже не очень сложна — но попробуйте добавить новые условия, и вы увидите, что она усложняется в разы.
Кроме того, если вы думаете, что создание новых классов вместо простого использования ветвящихся операторов звучит раздражающе, подождите, пока вы не увидите это в действии. Этот способ лаконичен и элегантен.
Даже лучше, это сделает вашу кодовую базу более SOLID, за исключением буквы ”D".
«Хорошо, я поверил, что if-else — это зло, теперь покажите мне, как избежать беспорядочного ветвящегося кода»
Мы рассмотрим, как я заменяю If-else в готовом к продакшену коде. Это выдуманный пример, но подход тот же, что я использовал в кодовых базах для крупных клиентов.
Давайте создадим очень простой класс
Booking
, который имеет несколько состояний. Он также будет иметь два паблик метода: Accept()
и Cancel()
.Я нарисовал диаграмму в меру своих возможностей, которая отображает различные состояния, в которых может находиться бронирование.

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

Обратите внимание, что этот класс также имеет два метода, Accept и Cancel — хотя здесь они помечены как внутренние.
Кроме того, базовое состояние имеет ”специальный" метод
EnterState(Booking booking)
. Он вызывается всякий раз, когда объекту бронирования присваивается новое состояние.Во-вторых, мы создаем отдельные классы для каждого состояния, которое хотим представлять.

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

Посмотрим, класс бронирования — это просто делегирование полномочий осуществления принятия и отклонения?
Это позволяет нам устранить большую часть условной логики и позволяет каждому состоянию сосредоточиться только на том, что важно для него самого — текущее состояние также имеет возможность перевести бронирование в новое состояние.
Как бороться с новыми условиями
Если новая функция обычно была реализована с помощью некоторой условной проверки, то теперь вы можете просто создать новый класс состояния.
Это очень просто. Вам больше не придется иметь дело с громоздким оператором if-else.
Как сохранить объект состояния в базе данных
Объект состояния не имеет значения при сохранении объекта, например, в базе данных SQL или NoSQL. Важно только знать состояние объекта и то, как оно должно быть отображено в столбце.
Вы можете сопоставить состояние с читаемым именем, перечислением или целым числом. Все, что вам удобно, пока у вас есть какой-то способ преобразовать сохраненное значение обратно в объект состояния.
Но ты все еще используешь «if»
Да, он очень важен. Особенно при использовании в качестве проверочных точек. Именно сочетание If-else является основной причиной головных болей поддержки кода.
Это же куча дополнительных классов
Действительно. Как я уже упоминал в другой статье, сложность возникает не из количества классов, которые у вас есть, а из обязанностей, которые эти классы берут на себя.
Наличие большого количества специализированных классов сделает ваш код более читаемым, поддерживаемым и просто более приятным для работы.

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:
- Курс по Machine Learning (12 недель)
- Обучение профессии Data Science с нуля (12 месяцев)
- Профессия аналитика с любым стартовым уровнем (9 месяцев)
- Курс «Python для веб-разработки» (9 месяцев)