Определяет семейство алгоритмов, инкапсулирует каждый из них и обеспечивает их взаимозаменяемость. Он позволяет модифицировать алгоритмы независимо от их использования на стороне клиента.
Назначение
Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Стратегия позволяет изменять алгоритмы независимо от клиентов, которые им пользуются.
Применимость
Используйте паттерн стратегия, когда:
- имеется много родственных классов, отличающихся только поведением. Стратегия позволяет сконфигурировать класс, задав одно из возможных поведений;
- вам нужно иметь несколько разных вариантов алгоритма. Например, можно определить два варианта алгоритма, один из которых требует больше времени, а другой - больше памяти.Стратегии разрешается применять, когда варианты алгоритмов реализованы в виде иерархии классов.
- в алгоритме содержаться данные о которых клиент не должен знать. Используйте паттерн стратегия, чтобы не раскрывать сложные, специфичные для алгоритма структуры данных;
- в классе определено много поведений, что представлено разветвленными условными операторами. В этом случае проще перенести код из ветвей в отдельные классы стратегий.
Структура
Участники
- Strategy - стратегия - объявляет общий для всех поддерживаемых алгоритмов интерфейс. Класс Context используется этим интерфейсом для вызова конкретного алгоритма, определенного в классе ConcreteStrategy;
- ConcreteStrategy - конкретная стратегия - реализует алгоритм, использующий интерфейс, объявленный в классе Strategy;
- Context - контекст:
- конфигурируется объектом класса oncreteStrategy;
- хранит ссылку на объект Strategy;
- может определять интерфейс, который позволяет объекту Strategy получить доступ к данным контекста.
Результаты
- семейства родственных алгоритмов;
- альтернатива порождению подклассов;
- с помощью стратегий можно избавиться от условных операторов;
- выбор реализации. Стратегии могут предлагать различные реализации одного и того же поведения. Клиент вправе выбирать подходящую стратегию в зависимости от своих требований к быстродействию и памяти;
- клиенты должны "знать" о различных стратегиях. Потенциальный недостаток этого паттерна в том, что для выбора подходящей стратегии клиент должен понимать чем отличаются разные стратегии. Поэтому наверняка придется раскрыть клиенту некоторые особенности реализации. Отсюда следует, что паттерн стратегия стоит применять лишь тогда, когда различия в поведении имеют значение для клиента;
- обмен информацией между стратегией и контекстом. Интерфейс класса Strategy разделяется всеми подклассами ConcreteSrategy - неважно, сложна или тривиальна их реализация. Поэтому вполне вероятно, что некоторые стратегии не будут пользоваться всей передаваемой им информацией, особенно простые. Это означает, что в отдельных случаях контекст создаст и проинициализирует параметры, которые никому не нужны. если возникнет проблема, то между классами Strategy и Context придется установить более тесную связь;
- увеличение числа объектов. Применении стратегий увеличивает число объектов в приложении. Иногда эти издержки можно сократить, если реализовать стратегии в виде объектов без состояния, которые могут разделяться несколькими контекстами. Остаточное состояние хранится в самом контексте и передается при каждом обращении к объекту-стратегии. Разделяемые стратегии не должны сохранять состояние между вызовами. В описании паттерна приспособленец этот подход обсуждается более подробно.