Skip to content

Pattern Strategy implementation

Notifications You must be signed in to change notification settings

alexandroid1/PatternStrategy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

2 Commits

Repository files navigation

PatternStrategy

Pattern Strategy implementation

Паттерн “Стратегия” — или опять про уток

(По книге O’Reilly — Head First — "Design Patterns")

На мой взгляд, книга O’Reilly "Head First — Design Patterns" - одна из лучших книг по паттернам - но когда я читал ее, у меня были кое-где неясности, и поэтому я решил написать эту статью.

Паттерн стратегия — самый простой из паттернов.

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

Для примера возьмем класс «утка» с методами «квак» и «показать».

image

Класс утка — суперкласс. От него мы будем наследовать.

Пусть у нас будут еще две утки — WildDuck и CityDuck.

image

У всех уток есть метод «display». Добавим еще резиновую утку, а в наш суперкласс добавим метод fly() - «летать».

image

Добавим еще несколько уток.

image

Но резиновые утки не летают. А у CloudDuck и MountainDuck один и тот же способ полета.

Т.е. у CloudDuck и MountainDuck будет одинаковый метод fly(), но отличающийся от метода fly() утки CloudDuck. Значит нужен другой класс для нового способа полета. Но это неправильный путь.

А что если нам нужно добавить метод eat(), и у разных видов уток он будет иметь разную реализацию? У нас в джаве нет множественного наследования (см. Ромбовидная проблема). Поэтому нам нужно другое решение.

Перейдем к решению проблемы.

Все наши классы — это клиенты для алгоритмов и они используют различные алгоритмы для реализации метода fly().

У нас есть алгоритм для метода fly() и алгоритм для метода Quack(). То есть мы должны создать стратегию для метода fly() и для метода Quack(). Мы должны извлечь эти методы чтобы использовать различные реализации.

Создадим интерфейс IQuackBehaviour для метода quack().

image

И создадим интерфейс IFlyBehaviour для метода fly().

image

Возможно даже было бы сделать из этих двух интерфейсов один интерфейс IDuckBehaviour.

Таким образом мы вынесли поведение уток за пределы класса Duck.

Интерфейс поведения будет реализовываться классами поведения, а не классом Duck.

Каждая утка будет иметь свой IFlyBehaviour и свой IQuackBehaviour.

image

Класс SimpleQuack реализует интерфейс IQuackBehaviour.

Мы можем сказать, что Quack() метод класса Duck передает полномочия интерфейсу IQuackBehaviour.

Когда мы вызываем метод Quack() класса Duck — мы запускаем метод Quack() класса SimpleDuck.

Резиновая утка не крякает, поэтому для нее будет еще одна реализация интерфейса.

image

Теперь класс Duck не должен заботиться о реализации кваканья уток. Класс Duck только должен иметь доступ к реализации интерфейса IQuackBehaviour.

Сделаем то же для IFlyBehaviour.

image

Можем поступить аналогично для метода Display().

image

SipmpleQuack, NoQuack, SimpleFly… — это конкретные стратегии.

На самом деле нам теперь не нужны сублассы WildDuck и CityDuck и мы можем их убрать.

image

Для удобства кодирования приведем нашу схему к следующему виду:

image

В IDE наши классы выглядят следующим образом:

image

Посмотрим на код.

Код класса "Реальная утка" выглядит следующим образом:

public class MallardDuck extends Duck{
public MallardDuck(){quackBehavior = new Quack(); flyBehaviour = new FlyWithWings()} @Override public void display(){System.out.println("I am a real Mallard Duck ")} 

}

Абстрактная утка — наш суперкласс. Код класса "Абстрактная утка" приведен ниже:

public abstract class Duck{
public QuackBehavior quackBehavior; public FlyBehaviour flyBehaviour; public Duck(){} public abstract void display(); public void performFly(){flyBehaviour.fly()} public void performQuack(){quackBehavior.quack()} public void swim(){System.out.println("All ducks float, even decoys!")} 

}

Рассмотрим интерфейсы с описанием поведения уток.

Код интерфейса "FlyBehaviour" приведен ниже:

public interface FlyBehaviour{public void fly()}

Код интерфейса "QuackBehavior":

public interface QuackBehavior{public void quack()}

Ниже приведен код конкретных стратегий поведения. Стратегия FlyNoWay:

public class FlyNoWay implements FlyBehaviour{@Override public void fly(){System.out.println("I can't fly")} }

Стратегия FlyWithWings:

public class FlyWithWings implements FlyBehaviour{@Override public void fly(){System.out.println("I am flying !")} }

Стратегия MuteQuack:

public class MuteQuack implements QuackBehavior{@Override public void quack(){System.out.println(" << Silence >> ")} }

Стратегия Quack:

public class Quack implements QuackBehavior{@Override public void quack(){System.out.println("Quack!")} }

Стратегия Squeak:

public class Squeak implements QuackBehavior{@Override public void quack(){System.out.println(" Squeak ")} }

Ниже приведен код класса "мини утиный симулятор":

public class MiniDuckSimulator{
public static void main(String[] args){Duck mallard = new MallardDuck(); mallard.performQuack(); mallard.performFly()} 

}

В данной статье мы рассмотрели самый простой из паттернов - паттерн "Стратегия".

Весь код можно посмотреть на моем гитхабе https://github.com/alexandroid1/PatternStrategy

Меня можно найти в соц сетях: Мой Linkedin https://www.linkedin.com/in/alexandroid1/ Моя личная страница ВК https://vk.com/sashapavlov Мой Instagramm https://www.instagram.com/aleksandr_7017/ Я в Facebook https://www.facebook.com/aleksandr7017

Ссылки на источники

1. Элизабет Фримен, Эрик Фримен, Кэти Сиерра, Берт Бейтс - "Паттерны проектирования". 2. Strategy Pattern – Design Patterns (ep 1) - https://www.youtube.com/watch?v=v9ejT8FO-7I

About

Pattern Strategy implementation

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published