Wednesday, May 31, 2017

Strategy Pattern

Strategy (from Greek: strategia, "art of troop leader; office of general, command, generalship") is a high level plan to achieve one or more goals under conditions of uncertainty.  A strategy describes how the ends (goals) will be achieved by the means (resources)

There are many scenarios in application development where there are multiple ways of doing the same operation. We want our application to have the possibility of using all these ways of performing the operations.

Below are some of the examples:

·      Online payment using a portal, I could choose to pay using net banking, or use a debit card, or use a credit card, or use PayPal for making the payment. All these are ways of performing the same operations. Though every choice will have to follow a different application logic, i.e. separate code.

·       Sorting algorithm: where the intention is same (i.e. need to sort, but by different ways).

·    Travel mode: one wants to arrive to different place but using different mode based on the current situation (he has less money – use cycle; has less time - use flight; it’s raining - use car), so he makes a clear strategy before his travel , he hires cycle, borrows money from his friend for the flight, books car tentatively).

So we have a situation to develop the application in such a way that for any operation the user could choose one of many available options, then perhaps that is the right place to incorporate the Strategy pattern.

The philosophy of the Strategy pattern is to have multiple strategies for doing some operation and let the user choose (or some algorithm based on input data) the appropriate strategy to carry out the operation.

GoF defines the Strategy pattern as “Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. 

·    Strategy: This is the interface common to all algorithms. Context uses this interface to perform the operations.
·     ConcreteStrategy: This is the class that implements the actual algorithm.
·   Context: This is the client application that performs the decision making for which strategy should be used and uses the Strategy interface (which is referring to a ConcreteStrategy object) to perform the operations.


To understand these concepts, let us take an application for converting audio files from Wav to MP3. Here the user will have an option of selecting the source .wav file and then select the quality of the target MP3 file to be created. The user interface will provide the user with three quality values for the target file.

In our code what we will do is that we will create multiple strategies each that we will be using are to define the quality of the output. We are implementing all these separate strategies so that conversion code will remain unaffected by the code that is specific to dealing with the quality of the output. The actual code that is doing the conversion will be independent of the implementation details of these different strategies and will work in the same fashion for any selected strategy or even when the new strategies are added.


IWavToMp3ConvertionStrategy interface for conversion:
interface IWavToMp3ConvertionStrategy
{
 void Convert();
}

Strategy class for low quality conversion
class LowQualityConversionStrategy : IWavToMp3ConvertionStrategy
{
 public void Convert()
 {
  Console.WriteLine("Low quality conversion performed");
 }
}

Strategy class for average quality conversion:
class AverageQualityConversionStrategy : IWavToMp3ConvertionStrategy
{
 public void Convert()
 {
  Console.WriteLine("Average quality conversion performed");
 }
}

Strategy class for high quality conversion:
//Strategy class for average quality conversion
class HighQualityConversionStrategy : IWavToMp3ConvertionStrategy
{
 public void Convert()
 {
  Console.WriteLine("High quality conversion performed");
 }
}
WavToMP3Convertor class to convert to different type:
public class WavToMP3Convertor
{
 AudioFile m_fileData = null;
 IWavToMp3ConvertionStrategy m_Convertor = null;

 public WavToMP3Convertor(AudioFile fileData)
 {
  m_fileData = fileData;            
 }
 
public void Convert(IWavToMp3ConvertionStrategy convertor)
 {
  m_Convertor = convertor;
  m_Convertor.Convert();            
 }
}
In main program we get use input and do the conversion:
static void Main(string[] args)
{
 IWavToMp3ConvertionStrategy selectedStrategy = null;

 Console.WriteLine("Assuming the file for conversion has been selected already");
 AudioFile file = new AudioFile { Title = "Sample File" };

 // Let us try to emulate the selection of quality here
 Console.WriteLine("Enter the type of output");
    
 int choice = Console.Read();

 // Based on the user's choice will select strategy to convert the file
 if (choice == '1')
 {
  selectedStrategy = new LowQualityConversionStrategy();                
 }
 else if (choice == '2')
 {
  selectedStrategy = new AverageQualityConversionStrategy();                
 }
 else if (choice == '3')
 {
  selectedStrategy = new HighQualityConversionStrategy();                
 }

 // Now the code which is doing the conversion. this code will
 // not be changes even if we implement more strategies
 if (selectedStrategy != null)
 {
  WavToMP3Convertor convertor = new WavToMP3Convertor(file);
  convertor.Convert(selectedStrategy);
 }
}
References:
https://sourcemaking.com/design_patterns/strategy
http://www.dofactory.com/javascript/strategy-design-pattern
https://stackoverflow.com/questions/5375187/strategy-design-pattern-and-factory-method-design-pattern

No comments:

Post a Comment