Why patterns?

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

В этом нам и помогут паттерны.

Nice Valdai


Ядро всех паттернов

В основе почти всех паттернов лежит простая концепция:

Изменение некоторой части системы должно быть независимо от других частей, не должно влиять на другие части системы

Эту концепция можно выразить иначе:

Выделите переменные состявляющие, аспекты приложения,которые могут изменяться, и отделите, инкапсулируйте их, чтобы позднее их можно было изменять или расширять без воздействия на постоянные составляющие.

Имитатор утиного пруда

Разберем следующий пример. Есть игра - утиный пруд, в котором плавают и крякают утки рахных видов.

3 - лаконично поддержать новое поведение “утки летают”.


Первая мысль

о том как пожжержать подобное решение , будет что-то вродe

Duck class Start

Однако данная реализация чревата пустыми методами, т.е непереопреденными. В итоге код будет избыточным.

Действительно,зачем наделять класс DecoyDuck() функциональностью, который он никогда не будет реализовывать.Деревянная уточка никгда не будет крякать.

Вторая мысль

Будет такая. а что если отказаться от одного общего класса в угоду нескольким интерфейсам и тогда наделить тот или иной Утиный класс соответсв. набором интерфейсов. Примерно так:

ducks_interfaced"

Однако тут мы сталкиваемся со следующей проблемой - эти интфейсы,нужно реализовывать каждый раз. и Нельзя сохранить и переиспользовать реализацию интефейса,т.е сохранить поведение.

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

Собственно, разные поведения - это разные стратегии.

Отделяем переменное от постоянного

Абстрактно, это будет выглядеть так:

abstract_solution

Проектирование переменного поведения

Требования у реализации такие:

  1. Инициализация *Duck с конкретным типом поведения fly()
  2. Runtime изменение поведения полета или крякания утки.

Принцип проектирования:

Программируйте на уровне интерфейсов, а не уровне реализации.

Таким образом , аспект поведения, т.е контракт поведения будет задаваться через interface, а конкретная реализация - через class, но фишка в том,что это будет класс отдельный , не класс Duck.

Duck не нужно знать подробности реализации своих аспектов поведения. Поведение будет инкасулировано от Duck в отдельных реализациях контракта данного поведения.

fly_behaviour

Интеграция поведения с классом Duck

Класс Duck теперь делегирует свои аспекты поведения(вместо простого использования методов,определенных в классе Duck или его субклассах)

  1. Сначала в класс Duck включаются две переменные экземпляров flyBehaviour and quackBehaviour, обьявленные с типом интерфейса. На стадии инициализации присваеваем конкретную реализацию поведения.

  2. Делегирование поведения - крякания и полета - в класс утка в perform методы: performQuack, performFly. т.е Именно в них будут вызываться методы делегированного поведения. Звучит пространно, поэтому приведем код.

   public class Duck{
   
   QuackBehaviour quackBehaviour;
   		
   	public void performQuack(){
   		quackBehaviour.quack();
   	}
  }

Приведем теперь полную реализацию на kotlin.

Inheritance vs composition

Каждая утка СОДЕРЖИТ экземпляры FlyBehaviour и QuackBehaviour, которым делегируется выполнение соотв. операций. Это механизм композиции. Поведение не наследуется, а предоставляется правильно выбранным обьектом.

Еще 1 преимущество перед наследованием : можно изменять поведение в runtime. Динамически.

Принцип проектирования : отдавайте предпочтение композиции перед наследованием.

Final Definition of Stratehy Pattern

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

Bonus : Kingdom people strategies


kingdom strategy