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