За информацията в тази статия или раздел не са посочени източници. Въпросната информация може да е непълна, неточна или изцяло невярна. Имайте предвид, че това може да стане причина за изтриването на цялата статия или раздел.
Шаблонът Стратегия се използва в случаите, когато е необходим динамичен избор на алгоритъм. Дефинира се семейство от различни, но взаемозаменяеми алгоритми, всеки един от тях капсулиран като отделен обект. Стратегията позволява превключването от един към друг алгоритъм да става независимо от клиентския код който ги използва.
Поведение
Съгласно шаблона Стратегия, поведението на конкретен клас не бива да се наследява. Вместо това трябва да се използва интерфейс, който дефинира външния вид на класовете които ще го наследяват и ще бъдат имплементирани.
Нека разгледаме като примерен класа Автомобил (Car). Възможни поведения за този клас са например Спиране (Brake) и Ускоряване (Accelerate). Тъй като тези две действия се изпълняват различно в зависимост от модела, е нужно различните поведения да се имплементират в подкласове. Ако се използва директно наследянаве на класа Автомобил (Car), това ще създаде спънка за организацията на класовете, тъй като за всеки нов модел ще трябва да се наследи и иплементира този клас наново. Така голяма част от кода ще се повтаря. С увеличаване на набора от модели, подкласовете също ще се увеличават. Също така за да се определи разликата в поведението на различните модели е нужно обстойно изследване на кода.
Шаблонът Стратегия използва композиция. Дадено поведение се дефинира като отделен интерфейс, който се имплементира от различни класове. По този начин се прави разделяне на поведението и класа, който използва това поведение. Поведението може да бъде променяно без знанието на класовете, които го използват. Също така даден клас може да превключва между различните поведения без значителни промени в кода. Поведенията могат да се сменят, както по време на дизайн, така и по време на изпълнение на програмата.
usingSystem;namespaceWikipedia.Patterns.Strategy{// MainApp test applicationclassMainApp{staticvoidMain(){ContextanObject;// Three contexts following different strategiesanObject=newContext(newConcreteStrategyA());anObject.Execute();anObject.UpdateContext(newConcreteStrategyB());anObject.Execute();anObject.UpdateContext(newConcreteStrategyC());anObject.Execute();}}// The classes that implement a concrete strategy must implement this Execute function.// The context class uses this to call the concrete strategyinterfaceIStrategy{voidExecute();}// Implements the algorithm using the strategy interfaceclassConcreteStrategyA:IStrategy{publicvoidExecute(){Console.WriteLine("Called ConcreteStrategyA.Execute()");}}classConcreteStrategyB:IStrategy{publicvoidExecute(){Console.WriteLine("Called ConcreteStrategyB.Execute()");}}classConcreteStrategyC:IStrategy{publicvoidExecute(){Console.WriteLine("Called ConcreteStrategyC.Execute()");}}// Configured with a ConcreteStrategy object and maintains a reference to a Strategy objectclassContext{IStrategystrategy;// ConstructorpublicContext(IStrategystrategy){this.strategy=strategy;}publicvoidUpdateContext(IStrategystrategy){this.strategy=strategy;}publicvoidExecute(){strategy.Execute();}}}
//StrategyExample test applicationclassStrategyExample{publicstaticvoidmain(String[]args){Contextcontext;// Three contexts following different strategiescontext=newContext(newConcreteStrategyAdd());intresultA=context.execute(3,4);context=newContext(newConcreteStrategySubtract());intresultB=context.execute(3,4);context=newContext(newConcreteStrategyMultiply());intresultC=context.execute(3,4);}}// The classes that implement a concrete strategy should implement this// The context class uses this to call the concrete strategyinterfaceStrategy{intexecute(inta,intb);}// Implements the algorithm using the strategy interfaceclassConcreteStrategyAddimplementsStrategy{publicintexecute(inta,intb){System.out.println("Called ConcreteStrategyA's execute()");return(a+b);// Do an addition with a and b}}classConcreteStrategySubtractimplementsStrategy{publicintexecute(inta,intb){System.out.println("Called ConcreteStrategyB's execute()");return(a–b);// Do a subtraction with a and b}}classConcreteStrategyMultiplyimplementsStrategy{publicintexecute(inta,intb){System.out.println("Called ConcreteStrategyC's execute()");returna*b;// Do a multiply with a and b}}// Configured with a ConcreteStrategy object and maintains a reference to a Strategy objectclassContext{Strategystrategy;// ConstructorpublicContext(Strategystrategy){this.strategy=strategy;}publicintexecute(inta,intb){returnthis.strategy.execute(a,b);}}
Тъй като езикът C не е обектно ориентиран, в него могат да се използват структури, за дефиниция на класове. Шаблонът Стратегия може да се реализира чрез използването на указатели към функции.
#include<stdio.h>voidprint_sum(intn,int*array){inttotal=0;for(inti=0;i<n;i++)total+=array[i];printf("%d",total);}voidprint_array(intn,int*array){for(inti=0;i<n;i++)printf("%d ",array[i]);}intmain(void){typedefstruct{void(*submit_func)(intn,int*array);char*label;}Button;// Create two instances with different strategiesButtonbutton1={print_sum,"Add 'em"};Buttonbutton2={print_array,"List 'em"};intn=10,numbers[n];for(inti=0;i<n;i++)numbers[i]=i;button1.submit_func(n,numbers);button2.submit_func(n,numbers);return0;}