Паттерн стратегии
В компьютерном программировании шаблон стратегии (также известный как шаблон политики ) представляет собой поведенческого шаблон проектирования программного обеспечения , который позволяет выбирать алгоритм во время выполнения. Вместо непосредственной реализации одного алгоритма код получает инструкции времени выполнения о том, какой из семейства алгоритмов следует использовать. [1]
Стратегия позволяет алгоритму изменяться независимо от клиентов, которые его используют. [2] Стратегия — один из шаблонов, включенных во влиятельную книгу « Шаблоны проектирования» Гаммы и др. [3] это популяризировало концепцию использования шаблонов проектирования для описания того, как создавать гибкое и повторно используемое объектно-ориентированное программное обеспечение. Откладывание решения о том, какой алгоритм использовать, до времени выполнения позволяет сделать вызывающий код более гибким и пригодным для повторного использования.
Например, класс, выполняющий проверку входящих данных, может использовать шаблон стратегии для выбора алгоритма проверки в зависимости от типа данных, источника данных, выбора пользователя или других различающих факторов. Эти факторы неизвестны до момента выполнения и могут потребовать выполнения совершенно иной проверки. Алгоритмы (стратегии) валидации, инкапсулированные отдельно от проверяющего объекта, могут использоваться другими проверяющими объектами в разных областях системы (или даже в разных системах) без дублирования кода .
Обычно шаблон стратегии сохраняет ссылку на код в структуре данных и извлекает ее. Этого можно достичь с помощью таких механизмов, как указатель на собственную функцию , функцию первого класса , классы или экземпляры классов в объектно-ориентированных языках программирования или доступ к внутреннему хранилищу кода реализации языка посредством отражения .
Структура [ править ]
Класс UML и диаграмма последовательности [ править ]

На приведенной выше UML классов диаграмме Context
класс не реализует алгоритм напрямую.
Вместо, Context
относится к Strategy
интерфейс для выполнения алгоритма ( strategy.algorithm()
), что делает Context
независимо от того, как реализован алгоритм.
Strategy1
и Strategy2
классы реализуют Strategy
интерфейс, то есть реализовать (инкапсулировать) алгоритм.
Диаграмма UML последовательности
показывает взаимодействие во время выполнения: Context
объект делегирует алгоритм различным Strategy
объекты. Первый, Context
звонки algorithm()
на Strategy1
объект,
который выполняет алгоритм и возвращает результат Context
.
После этого Context
меняет свою стратегию и призывает algorithm()
на Strategy2
объект,
который выполняет алгоритм и возвращает результат Context
.
Диаграмма классов [ править ]


Стратегия и принцип открытости/закрытости [ править ]

Согласно шаблону стратегии, поведение класса не должно наследоваться. Вместо этого их следует инкапсулировать с помощью интерфейсов. Это совместимо с принципом открытости/закрытости (OCP), который предполагает, что классы должны быть открыты для расширения, но закрыты для модификации.
В качестве примера рассмотрим класс автомобиля. Две возможные функции автомобиля: торможение и ускорение . Поскольку поведение ускорения и торможения часто меняется в зависимости от модели, общепринятым подходом является реализация этого поведения в подклассах. Этот подход имеет существенные недостатки; Режимы ускорения и торможения должны быть указаны в каждой новой модели автомобиля. Работа по управлению этим поведением значительно возрастает по мере увеличения количества моделей и требует дублирования кода между моделями. Кроме того, нелегко определить точную природу поведения каждой модели, не исследуя код каждой.
Шаблон стратегии использует композицию вместо наследования . В шаблоне стратегии поведение определяется как отдельные интерфейсы и конкретные классы, реализующие эти интерфейсы. Это позволяет лучше отделить поведение от класса, который его использует. Поведение можно изменить, не нарушая работу классов, которые его используют, а классы могут переключаться между поведениями путем изменения конкретной используемой реализации, не требуя каких-либо существенных изменений кода. Поведение также можно изменить как во время выполнения, так и во время разработки. Например, поведение тормоза объекта автомобиля можно изменить с BrakeWithABS()
к Brake()
путем изменения brakeBehavior
член, чтобы:
brakeBehavior = new Brake();
/* Encapsulated family of Algorithms
* Interface and its implementations
*/
public interface IBrakeBehavior {
public void brake();
}
public class BrakeWithABS implements IBrakeBehavior {
public void brake() {
System.out.println("Brake with ABS applied");
}
}
public class Brake implements IBrakeBehavior {
public void brake() {
System.out.println("Simple Brake applied");
}
}
/* Client that can use the algorithms above interchangeably */
public abstract class Car {
private IBrakeBehavior brakeBehavior;
public Car(IBrakeBehavior brakeBehavior) {
this.brakeBehavior = brakeBehavior;
}
public void applyBrake() {
brakeBehavior.brake();
}
public void setBrakeBehavior(IBrakeBehavior brakeType) {
this.brakeBehavior = brakeType;
}
}
/* Client 1 uses one algorithm (Brake) in the constructor */
public class Sedan extends Car {
public Sedan() {
super(new Brake());
}
}
/* Client 2 uses another algorithm (BrakeWithABS) in the constructor */
public class SUV extends Car {
public SUV() {
super(new BrakeWithABS());
}
}
/* Using the Car example */
public class CarExample {
public static void main(final String[] arguments) {
Car sedanCar = new Sedan();
sedanCar.applyBrake(); // This will invoke class "Brake"
Car suvCar = new SUV();
suvCar.applyBrake(); // This will invoke class "BrakeWithABS"
// set brake behavior dynamically
suvCar.setBrakeBehavior( new Brake() );
suvCar.applyBrake(); // This will invoke class "Brake"
}
}
См. также [ править ]
- Внедрение зависимостей
- Функция высшего порядка
- Список терминов объектно-ориентированного программирования
- смешивание
- Проектирование на основе политик
- Тип класса
- Сущность-компонент-система
- Композиция важнее наследования
Ссылки [ править ]

- ^ «Шаблон разработки стратегии: проблема, решение и применимость» . w3sDesign.com . Проверено 12 августа 2017 г.
- ^ Эрик Фриман, Элизабет Фриман, Кэти Сьерра и Берт Бейтс, Шаблоны проектирования Head First , первое издание, глава 1, страница 24, O'Reilly Media, Inc, 2004. ISBN 978-0-596-00712-6
- ^ Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес (1994). Шаблоны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования . Эддисон Уэсли. стр. 315 и далее . ISBN 0-201-63361-2 .
{{cite book}}
: CS1 maint: несколько имен: список авторов ( ссылка ) - ^ «Шаблон разработки стратегии — структура и сотрудничество» . w3sDesign.com . Проверено 12 августа 2017 г.
- ^ «Краткий справочник по шаблонам проектирования – McDonaldLand» .
Внешние ссылки [ править ]

- Шаблон стратегии в UML (на испанском языке)
- Гири, Дэвид (26 апреля 2002 г.). «Стратегия успеха» . Шаблоны проектирования Java. JavaWorld . Проверено 20 июля 2020 г.
- Статья о паттерне стратегии для C
- Рефакторинг: замена кода типа на состояние/стратегию
- Шаблон проектирования стратегии на Wayback Machine (архивировано 15 апреля 2017 г.). Реализация шаблона стратегии в JavaScript.