С одной стороны, большие скопления if/else
блоков не легко проверить . Каждая новая «ветвь» добавляет другой путь выполнения и, таким образом, увеличивает цикломатическую сложность . Если вы хотите тщательно протестировать свой код, вам нужно будет охватить все пути выполнения, и каждое условие потребует от вас написать хотя бы еще один тест (при условии, что вы пишете небольшие, сфокусированные тесты). С другой стороны, классы, которые реализуют стратегии, обычно предоставляют только один публичный метод, который легко протестировать.
Таким образом, с вложенными if/else
вы получите множество тестов для одной части вашего кода, в то время как со Стратегией у вас будет несколько тестов для каждой из нескольких более простых стратегий. С последним легче получить лучший охват, потому что труднее пропустить пути выполнения.
Что касается расширяемости , представьте, что вы пишете фреймворк, в котором пользователи должны иметь возможность внедрять свое собственное поведение. Например, вы хотите создать некую структуру налоговых расчетов и хотите поддерживать налоговые системы разных стран. Вместо того, чтобы реализовывать их все, вы просто хотите дать пользователям фреймворка возможность представить, как рассчитывать некоторые конкретные налоги.
Вот образец стратегии:
- Вы определяете интерфейс, например
TaxCalculation
, и ваша структура принимает экземпляры этого типа для расчета налогов
- Пользователь фреймворка создает класс, который реализует этот интерфейс и передает его в фреймворк, тем самым предоставляя способ выполнить некоторую часть вычислений.
Вы не можете сделать то же самое с if/else
, потому что это потребует изменения кода фреймворка, и в этом случае он больше не будет фреймворком. Поскольку платформы часто распространяются в скомпилированном виде, это может быть единственным вариантом.
Тем не менее, даже если вы просто пишете какой-то обычный код, стратегия выгодна, потому что она проясняет ваши намерения. В нем говорится «эта логика является подключаемой и условной», то есть может быть несколько реализаций, которые могут варьироваться в зависимости от действий пользователя, конфигурации или даже платформы.
Использование шаблона «Стратегия» может улучшить читабельность, потому что, хотя класс, который реализует какую-то конкретную стратегию, обычно должен иметь описательное имя, например USAIncomeTaxCalculator
, if/else
блоки являются «безымянными», в лучшем случае просто прокомментированными, а комментарии могут лгать. Кроме того, по моему личному вкусу, просто более трех if/else
блоков подряд не читаются, и это плохо работает с вложенными блоками.
Принцип Open / Closed также очень важен, потому что, как я описал в примере выше, Strategy позволяет расширять логику в некоторых частях вашего кода («открыто для расширения»), не переписывая эти части («закрыто для модификации»). ).