Паттерн стратегии — это группа алгоризмов или бизнес-логик, каждый из которых взаимозаменяем.
Паттерн стратегии отделяет алгоритмы от клиентов, которые их используют, так что мы можем изменять алгоритмы, не трогая клиентов.
Сценарная проблема
Вот простой пример. У нас есть класс Animal, от которого наследуются 4 различных дочерних класса (Horse, Sheep, Lion и Bird).
Может быть очень просто реализовать методы eat()
и move()
в каждом из дочерних классов. Однако иногда некоторые из дочерних классов могут иметь одинаковую реализацию.
Как мы видим в этом примере, лошадь и овца имеют одинаковое поведение eat()
(Есть траву); лошадь, овца и лев имеют одинаковое поведение move()
(Ходить).
Теперь это дублирование кода демонстрирует неприятные запахи, в то время как у нас всего 4 класса. Представьте, насколько безумной будет ситуация, если классов будет 10 или больше? 🤯
Решение
Теперь в дело вступает шаблон стратегии.
Мы меняем eat()
и move()
на интерфейсы EatStrategy и MoveStrategy, и класс Animal имеет свойства этих стратегий, как показано на следующей диаграмме.
Теперь мы отделили поведение поедания и перемещения от класса Animal. Преимущество заключается в том, что когда мы изменяем любое из поведений перемещения или приема пищи (бизнес-логин), нам не нужно трогать животное (использующего его клиента), как раньше. Кроме того, у нас не будет дублирующихся кодов.
Окончательный код будет выглядеть следующим образом:
MoveStrategy walk = new WalkStrategy();
MoveStrategy fly = new FlyStrategy();
EatStrategy eatGrass = new EatGrassStrategy();
EatStrategy eatMeat = new EatMeatStrategy();
EatStrategy eatGrains = new EatGrainsStrategy();
Animal horse = new Animal(walk, eatGrass);
Animal sheep = new Animal(walk, eatGrass);
Animal sion = new Animal(walk, eatMeat);
Animal bird = new Animal(fly, eatGrain);