article

In computer programming, the strategy pattern is a particular software design pattern, whereby algorithms can be selected on-the-fly at runtime.

The strategy pattern is useful for situations where it is necessary to dynamically swap the algorithms used in an application. The strategy pattern is intended to provide a means to define a family of algorithms, encapsulate each one as an object, and make them interchangeable. The strategy pattern lets the algorithms vary independently from clients that use them.

Example


Sample Code in C#; Strategy - Interface: The classes that implement a concrete strategy should implement it. The context class uses this to call the concrete strategy. ConcreteStrategy: Implements the algorithm using the strategy interface. Context: configured with a ConcreteStrategy object and maintains a reference to a Strategy object

using System;

namespace Wikipedia.Patterns.Strategy { // MainApp test application class MainApp { static void Main() { Context context; // Three contexts following different strategies context = new Context(new ConcreteStrategyA()); context.Execute();

context = new Context(new ConcreteStrategyB()); context.Execute();

context = new Context(new ConcreteStrategyC()); context.Execute(); Console.Read(); } }

// "Strategy" interface Strategy { void Execute(); }

// "ConcreteStrategyA" class ConcreteStrategyA : Strategy { public void Execute() { Console.WriteLine( "Called ConcreteStrategyA.Execute()"); } }

// "ConcreteStrategyB" class ConcreteStrategyB : Strategy { public void Execute() { Console.WriteLine( "Called ConcreteStrategyB.Execute()"); } }

// "ConcreteStrategyC" class ConcreteStrategyC : Strategy { public void Execute() { Console.WriteLine( "Called ConcreteStrategyC.Execute()"); } }

// "Context" class Context { Strategy strategy;

// Constructor public Context(Strategy strategy) { this.strategy = strategy; }

public void Execute() { strategy.Execute(); } } }

Practical Example


Imagine class Strategy is an interface for a sorting-algorithm. Then class ConcreteStrategyA could be named BubbleSort and class ConcreteStrategyB could be named QuickSort. The class Context could be named ArraySorter if one only needs to sort arrays. The context basically gives a hint on the problem domain - in this case an array sorting-machine.

So the Strategy pattern gives the client the option to choose between sorting-routines. While the Strategy pattern implements polymorphic behavior of the "big picture", the Template method pattern implements polymorphic behavior of the "details". Think of a sorting-algorithm that is able to sort in descending and ascending order.

The Strategy pattern is suited for implementing polymorphic behavior of the details of algorithms as well. Extending the polymorphic behaviour won't break communication between objects like the way the Template method pattern could. This could happen in the case of a radical expansion of the detail-classes. But using the Strategy pattern for polymorphic details means one needs to maintain four classes. The Template method pattern needs one class less, so the overhead may be less as well.

C++ Code Example

C++ example of two sorting-algorithms both able to sort in ascending and descending order following below. Bold names like Sorter.h and Sorter.cpp are the filenames to be included in your C++ project. They are not part of the code. Italics are not part of the code as well and are only comments on code belonging to the filename.

The code is lengthy, split up in header- and implementation files. It's purpose is to play with it. The code is complete and compilable.

ConsoleClient.cpp

By default this file is called "main.cpp". This is the driver of the program. It should demonstrate in a blink of an eye the interchangebility of the algorithms and the implementations (sorting by ascending or descending order).

#include "Sorter.h" #include "Order.h" #include "Ascending.h" #include "Descending.h" #include "BubbleSort.h" #include "CombSort.h" #include <iostream> #include <string> #include <cstddef>
int main() {   std::string sLeaderTypes*={ "President""Queen""Warlord""Ceasar",     "Prime Minister""Emperor""Archduke"};   const std::size_t size = sizeof sLeaderTypes / sizeof *sLeaderTypes;
  //












---
  Sorter* S*//2 Sorters x 2 Orderings = 4   Order* Ord*;   Ord* = new Ascending;   Ord* = new Descending;   //BubbleSort sorting in ascending order.   SCOLOR=#0000FF>new BubbleSort(sLeaderTypes, size, Ord[0);    //BubbleSort sorting in descending order.   SCOLOR=#0000FF>new BubbleSort(sLeaderTypes, size, Ord[1);   //CombSort sorting in ascending order.   SCOLOR=#0000FF>new CombSort(sLeaderTypes, size, Ord[0);   //CombSort sorting in descending order.   SCOLOR=#0000FF>new CombSort(sLeaderTypes, size, Ord[1);
  //











-

  S*->Sort(); //BubbleSort sorting in ascending order.   for(std::size_t i = 0; i < size; ++i)   {     std::cout<<sLeaderTypes*<<std::endl;   }   std::cout<<std::endl;   //--     S*->Sort(); //BubbleSort sorting in descending order.   for(std::size_t i = 0; i < size; ++i)   {     std::cout<<sLeaderTypes*<<std::endl;   }   std::cout<<std::endl;   //--   S*->Sort(); //CombSort sorting in ascending order.   for(std::size_t i = 0; i < size; ++i)   {     std::cout<<sLeaderTypes*<<std::endl;   }   std::cout<<std::endl;   //--   S*->Sort(); //CombSort sorting in descending order.   for(std::size_t i = 0; i < size; ++i)   {     std::cout<<sLeaderTypes*<<std::endl;   }   std::cout<<std::endl;   //--
  delete OrdCOLOR=#0000FF>delete Ord[1;   delete SCOLOR=#0000FF>delete S*COLOR=#0000FF>delete S[3;
  return 0; } Sorter.h

Base class for the the two sorting algorithms: QuickSort and CombSort. #ifndef ABSTRACTION_H_HEADER_INCLUDED_BB5208E4 #define ABSTRACTION_H_HEADER_INCLUDED_BB5208E4
#include "Order.h" #include <string> #include <cstddef>

//From the design pattern: BRIDGE
class Sorter { public:   // Constructor   Sorter(std::string*, const std::size_t, Order*);
  //_Order->Sort();   virtual void Sort()=0;
protected:    /*virtual*/ void Swap(std::string&, std::string&); //_Order->Swap()   /*virtual*/ bool OutOfOrder(const std::string&, const std::string&); //_Order->OutOfOrder()
protected:     std::string* _Array;   const std::size_t _Size; private:   Order* _Order; };

#endif /* ABSTRACTION_H_HEADER_INCLUDED_BB5208E4 */ BubbleSort.h #ifndef REFINEDABSTRACTION_H_HEADER_INCLUDED_BB5223FD #define REFINEDABSTRACTION_H_HEADER_INCLUDED_BB5223FD
#include "Sorter.h"
class BubbleSort : public Sorter { public:   BubbleSort(std::string*, const std::size_t, Order*); public:   void Sort();
};

#endif /* REFINEDABSTRACTION_H_HEADER_INCLUDED_BB5223FD */ CombSort.h #ifndef COMBSORT_H_HEADER_INCLUDED_BB5270CA #define COMBSORT_H_HEADER_INCLUDED_BB5270CA
#include "Sorter.h"
class CombSort : public Sorter { public:   CombSort(std::string*, const std::size_t, Order*); public:   void Sort(); private:   static int NewGap(int); };

#endif /* COMBSORT_H_HEADER_INCLUDED_BB5270CA */ Order.h #ifndef IMPLEMENTOR_H_HEADER_INCLUDED_BB522635 #define IMPLEMENTOR_H_HEADER_INCLUDED_BB522635
#include <string>
//From the design pattern:BRIDGE
class Order { public:   // Constructor   Order();
  /** Summary */   virtual bool OutOfOrder(const std::string&, const std::string&) const = 0;   virtual void Swap(std::string&, std::string&);
};
#endif /* IMPLEMENTOR_H_HEADER_INCLUDED_BB522635 */ Ascending.h #ifndef CONCRETEIMPLEMENTORA_H_HEADER_INCLUDED_BB523269 #define CONCRETEIMPLEMENTORA_H_HEADER_INCLUDED_BB523269
#include "Order.h" #include <string>
//  class Ascending : public Order { public:   //    bool OutOfOrder(const std::string&, const std::string& ) const;
};

#endif /* CONCRETEIMPLEMENTORA_H_HEADER_INCLUDED_BB523269 */ Descending.h #ifndef CONCRETEIMPLEMENTORB_H_HEADER_INCLUDED_BB521380 #define CONCRETEIMPLEMENTORB_H_HEADER_INCLUDED_BB521380
#include "Order.h" #include <string>
class Descending : public Order { public:   //    bool OutOfOrder(const std::string&, const std::string&) const;
};

#endif /* CONCRETEIMPLEMENTORB_H_HEADER_INCLUDED_BB521380 */ Sorter.cpp #include "Sorter.h"
Sorter::Sorter(std::string* array, const std::size_t size, Order* ord) :    _Array(array), _Size(size), _Order(ord) {}
void Sorter::Swap(std::string& a, std::string& b) {   _Order->Swap(a, b); }
bool Sorter::OutOfOrder(const std::string& a, const std::string& b) {   return _Order->OutOfOrder(a, b); }

BubbleSort.cpp #include "BubbleSort.h"
BubbleSort::BubbleSort(std::string* array, const std::size_t size, Order* ord) :   Sorter(array, size, ord) {}
void BubbleSort::Sort() {   for(std::size_t i = _Size; i-- > 0;)   {     for(std::size_t j= 0 ; j < _Size-1 ; j++)     {       if(OutOfOrder(_Array*, _Array*) )         Swap( _Array*, _Array* );     }   } }
CombSort.cpp #include "CombSort.h"
CombSort::CombSort(std::string* array, const std::size_t size, Order* ord) :      Sorter(array, size, ord) {}
void CombSort::Sort() {   unsigned Size = static_cast<unsigned> (_Size);   unsigned gap = Size;   while(true)   {     gap = NewGap(gap);     bool swapped = false;     for(unsigned j= 0 ; j<Size-gap ; j++)       if(OutOfOrder(_Array*, _Array* ))       {         Swap(_Array*, _Array* );         swapped = true;       }       if(gap == 1 && !swapped)         break;   } }
int CombSort::NewGap(int gap) {   gap = (gap * 10) / 13;   if (gap 

 9 || gap 


 10)     gap = 11;   if (gap < 1)     gap = 1;   return gap; }
Order.cpp #include "Order.h"
void Order::Swap(std::string& a, std::string& b) {   std::string tmp = a;   a = b;   b = tmp; }
Order::Order() { }
Ascending.cpp #include "Ascending.h"
bool Ascending::OutOfOrder(const std::string& a, const std::string& b) const {   return a > b; }
Descending.cpp #include "Descending.h"
bool Descending::OutOfOrder(const std::string& a, const std::string& b) const {   return a < b; }

Strategy versus Bridge


The UML case diagram for the Strategy pattern is the same as the diagram for the Bridge pattern. However, these two design patterns aren't the same in their intent. While the Strategy pattern is meant for behavior, the Bridge pattern is meant for structure. The coupling between the context and the strategies is tighter than the coupling between the abstraction and the implementation in the Bridge pattern.

See also


External links


Software design patterns

Strategie (Entwurfsmuster) | Strategy (patrón de diseño) | Stratégie (motif de conception) | Strategy pattern | Wzorzec strategii

 

This article is licensed under the GNU Free Documentation License. It uses material from the "Strategy pattern".

Home Pageartsbusinesscomputersgameshealthhospitalshomekids & teensnewsphysiciansrecreationreferenceregionalscienceshoppingsocietysportsworld