Стратегия (шаблон проектирования)

Стратегия (англ. Strategy) — поведенческий шаблон проектирования, предназначенный для определения семейства алгоритмов, инкапсуляции каждого из них и обеспечения их взаимозаменяемости. Это позволяет выбирать алгоритм путём определения соответствующего класса. Шаблон Strategy позволяет менять выбранный алгоритм независимо от объектов-клиентов, которые его используют.

Стратегия
Strategy
Представление структуры шаблона Strategy
Тип поведенческий
Назначение позволяет использовать различные бизнес-правила или алгоритмы в зависимости от контекста.
Применяется в случаях когда в одном и том же месте в зависимости от текущего состояния системы (или её окружения) должны использоваться различные алгоритмы
Плюсы
  • инкапсуляция реализации различных алгоритмов, система становится независимой от возможных изменений бизнес-правил;
  • вызов всех алгоритмов одним стандартным образом;
  • отказ от использования переключателей и/или условных операторов.
Минусы создание дополнительных классов
Родственные шаблоны Мост, Шаблонный метод, Адаптер
Описан в Design Patterns Да

Основные характеристикиПравить

ЗадачаПравить

По типу клиента (или по типу обрабатываемых данных) выбрать подходящий алгоритм, который следует применить. Если используется правило, которое не подвержено изменениям, нет необходимости обращаться к шаблону «стратегия».

МотивыПравить

  • Программа должна обеспечивать различные варианты алгоритма или поведения
  • Нужно изменять поведение каждого экземпляра класса
  • Необходимо изменять поведение объектов на стадии выполнения
  • Введение интерфейса позволяет классам-клиентам ничего не знать о классах, реализующих этот интерфейс и инкапсулирующих в себе конкретные алгоритмы

Способ решенияПравить

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

УчастникиПравить

  • Класс Strategy определяет, как будут использоваться различные алгоритмы.
  • Конкретные классы ConcreteStrategy реализуют эти различные алгоритмы.
  • Класс Context использует конкретные классы ConcreteStrategy посредством ссылки на конкретный тип абстрактного класса Strategy. Классы Strategy и Context взаимодействуют с целью реализации выбранного алгоритма (в некоторых случаях классу Strategy требуется посылать запросы классу Context). Класс Context пересылает классу Strategy запрос, поступивший от его класса-клиента.

СледствияПравить

  • Шаблон Strategy определяет семейство алгоритмов.
  • Это позволяет отказаться от использования переключателей и/или условных операторов.
  • Вызов всех алгоритмов должен осуществляться стандартным образом (все они должны иметь одинаковый интерфейс).

РеализацияПравить

Класс, который использует алгоритм (Context), включает абстрактный класс (Strategy), обладающий абстрактным методом, определяющим способ вызова алгоритма. Каждый производный класс реализует один требуемый вариант алгоритма.

Замечание: метод вызова алгоритма не должен быть абстрактным, если требуется реализовать некоторое поведение, принимаемое по умолчанию.

Полезные сведенияПравить

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

ИспользованиеПравить

Архитектура Microsoft WDF основана на этом паттерне. У каждого объекта «драйвер» и «устройство» есть неизменяемая часть, вшитая в систему, в которой регистрируется изменяемая часть (стратегия), написанная в конкретной реализации. Изменяемая часть может быть и вовсе пустой, что даст ничего не делающий драйвер, но при этом способный участвовать в PnP и управлении питанием.

Библиотека ATL содержит в себе набор классов threading model, которые являются стратегиями (различными реализациями Lock/Unlock, которые потом используются основными классами системы). При этом в этих стратегиях используется статический полиморфизм через параметр шаблона, а не динамический полиморфизм через виртуальные методы.

ПримерыПравить

Пример на Java

Пример на C++

Пример на C#

Примеры на D

Пример на Delphi

Примеры на Javascript

Примеры на PHP

Пример на Python 2.7

Пример на Ruby

Источники информацииПравить

  • Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес. Приемы объектно-ориентированного проектирования. Паттерны проектирования = Design Patterns: Elements of Reusable Object-Oriented Software. — СПб: «Питер», 2007. — С. 366. — ISBN 978-5-469-01136-1. (также ISBN 5-272-00355-1)
  • Шаллоуей, Алан, Тротт, Джейм, Р. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию: Пер. с англ. —М.: Издательский дом «Вильямс», 2002. —288 с. ISBN 5-8459-0301-7
  • Grand, M. Шаблоны проектирования в Java: Пер. с англ.. — М.: Новое знание, 2004. — С. 559. — ISBN 5-94735-047-5.