Паттерн Стратегия
Класс Compressor содержит указатель на объект абстрактного типа Compression и предназначен для переадресации пользовательских запросов конкретному алгоритму. Для замены одного алгоритма другим достаточно перенастроить этот указатель на объект нужного типа. Важно, чтобы все стратегии имели общий интерфейс. Используя этот интерфейс, контекст будет независимым от конкретных классов стратегий.
- Для контекста неважно, какая именно вариация алгоритма будет выбрана, так как все они имеют одинаковый интерфейс.
- Каждая ветка такого оператора представляет собой вариацию алгоритма.
- Реализацию на PHP приводить не буду, так как она довольно простая, если понять суть применения паттерна на практике.
- Затем контекст получает определённый объект-стратегию от клиента и делегирует ему работу.
- Система, построенная на основе наследования, является статичной.
- Определите алгоритм, который подвержен частым изменениям.
Если с популярностью навигатора не было никаких проблем, то техническая часть вызывала вопросы и периодическую головную боль. С каждым новым алгоритмом код основного класса навигатора увеличивался вдвое. В таком большом классе стало довольно трудно ориентироваться. Первая версия вашего навигатора могла прокладывать маршрут лишь по дорогам, поэтому отлично подходила для путешествий на автомобиле.
Постараюсь изложить свой ход мысли, возможно, он будет понятнее, чем сухие выдержки из сборников паттернов, которые все пытаются подать в том или ином виде при его рассмотрении. Клиент должен знать, в чём состоит разница между стратегиями, чтобы выбрать подходящую. Усложняет программу за счёт дополнительных классов. Через некоторое время выяснилось, что некоторые люди предпочитают ездить по городу на общественном транспорте. Поэтому вы добавили и такую опцию прокладывания пути.
Недостатки паттерна Strategy
Заменить один алгоритм на другой в ходе выполнения программы уже невозможно. С другой стороны, Стратегия описывает разные способы произвести одно и то же действие, позволяя взаимозаменять эти способы в каком-то объекте контекста. Изолирует код и данные алгоритмов от остальных классов. Клиенты контекста должны подавать в него соответствующий объект-стратегию, когда хотят, чтобы контекст вёл себя определённым образом. Конкретные стратегии реализуют различные вариации алгоритма.
Стратегия определяет интерфейс, общий для всех вариаций алгоритма. Контекст использует этот интерфейс для вызова алгоритма. Можно доехать на автобусе, такси или велосипеде. Вы выбираете конкретную стратегию в зависимости от контекста — наличия денег или времени до отлёта. Любое изменение алгоритмов поиска, будь то исправление багов или добавление нового алгоритма, затрагивало основной класс. Это повышало риск сделать ошибку, случайно задев остальной работающий код.
Состояние можно рассматривать как надстройку над Стратегией. Оба паттерна используют композицию, чтобы менять поведение основного объекта, делегируя работу вложенным объектам-помощникам. Однако в Стратегии эти объекты не знают друг о друге и никак не связаны.
Когда у вас есть множество похожих классов, отличающихся только некоторым поведением. В ближайшей перспективе вы хотели бы добавить прокладывание маршрутов по велодорожкам. А в отдалённом будущем — интересные маршруты посещения достопримечательностей. Реализация паттерна «Стратегия» лишена этого недостатка. Всегда можно применить любой набор существующих поведений и расширять его до бесконечности без необходимости каких-либо изменений структуры приложения. Но наследование не позволяет получить ни поведение не из родителя, ни различное поведение от двух разных родителей.
В этих классах будет определён лишь один метод, принимающий в параметрах координаты начала и конца пути, а возвращающий массив точек маршрута. Реализацию на PHP приводить не буду, так как она довольно простая, если понять суть применения паттерна на практике. Проблему может вызвать только необходимость иметь что-то вроде фабрики или фабричного метода для создания нужной реализации конкретного поведения объекта. Но это можно легко сделать при помощи механизма внедрения зависимостей , без которого не обходится ни один проект. Стратегия позволяет вынести отличающееся поведение в отдельную иерархию классов, а затем свести первоначальные классы к одному, сделав поведение этого класса настраиваемым. Паттерн Стратегия предлагает определить семейство схожих алгоритмов, которые часто изменяются или расширяются, и вынести их в собственные классы, называемые стратегиями.
Зачем нужен паттерн «Стратегия»
Благодаря этому, fxtm не будет знать о том, какая именно стратегия сейчас выбрана. Во время выполнения программы контекст получает вызовы от клиента и делегирует их объекту конкретной стратегии. Хотя каждый класс будет прокладывать маршрут по-своему, для навигатора это не будет иметь никакого значения, так как его работа заключается только в отрисовке маршрута.
Число классов в системе, построенной с применением паттерна Strategy, возрастает. Реализация алгоритма жестко привязана к его подклассу, что затрудняет поддержку и расширение такой системы. Определите алгоритм, который подвержен частым изменениям. Также подойдёт алгоритм, имеющий несколько вариаций, которые выбираются во время выполнения программы. В этом примере контекст использует Стратегию для выполнения той или иной арифметической операции. Если есть поведение, то должен быть интерфейс, его реализация, и эта реализация должна внедряться как зависимость.
Паттерны поведения
С другой стороны, вы сможете изменять и добавлять новые виды алгоритмов, не трогая код контекста. Шаблонный метод использует наследование, чтобы расширять части алгоритма. Стратегия использует делегирование, чтобы изменять выполняемые алгоритмы на лету. Стратегия позволяет менять логику отдельных объектов.
Поэтому следующим шагом вы добавили в навигатор прокладывание пеших маршрутов. Поведение объекта делегируется другому объекту, который реализует это поведение. В итоге делегат реализует поведение и является зависимостью для объекта, поведение которого он реализует.
https://fxdu.ru/ помещает каждую лапу такого оператора в отдельный класс-стратегию. Затем контекст получает определённый объект-стратегию от клиента и делегирует ему работу. Если вдруг понадобится сменить алгоритм, в контекст можно подать другую стратегию. Стратегия позволяет изолировать код, данные и зависимости алгоритмов от других объектов, скрыв эти детали внутри классов-стратегий. Стратегия позволяет варьировать поведение объекта во время выполнения программы, подставляя в него различные объекты-поведения (например, отличающиеся балансом скорости и потребления ресурсов). Контекст хранит ссылку на объект конкретной стратегии, работая с ним через общий интерфейс стратегий.
Вместо интерфейса здесь также можно было бы использовать абстрактный класс. Клиент должен создать объект конкретной стратегии и передать его в конструктор контекста. Кроме этого, клиент должен иметь возможность заменить стратегию на лету, используя сеттер.
Обычного наследования недостаточно: зачем использовать паттерн «Стратегия» в разработке
Сделать это можно на этапе создания объекта, просто передав в конструктор требуемый экземпляр реализации поведения. Паттерн Стратегия представляет шаблон проектирования, который определяет набор алгоритмов, инкапсулирует каждый из них и обеспечивает их взаимозаменяемость. В зависимости от ситуации мы можем легко заменить один используемый алгоритм другим. При этом замена алгоритма происходит независимо от объекта, который использует данный алгоритм.
В Состоянии сами конкретные состояния могут переключать контекст. Начать можно с обычного делегирования, чтобы отделить поведение от данных и вынести реализацию поведения в отдельный объект. Если в будущем появится необходимость реализации нескольких вариантов поведения, можно реализовать интерфейс для поведения и перейти к паттерну «Стратегия». Интерфейс IStrategy, который определяет метод Algorithm(). Это общий интерфейс для всех реализующих его алгоритмов.