Behavioral Design Patterns provide solution for the better interaction between objects and how to provide lose coupling and flexibility to extend easily. Following design patterns come under this category.
Strategy pattern allows you to switch the algorithm or strategy based upon the situation.
The Strategy pattern is useful when there is a set of related algorithms and a client object needs to be able to dynamically pick and choose an algorithm from this set that suits its current need. The Strategy pattern suggests keeping the implementation of each of the algorithms in a separate class. Each such algorithm encapsulated in a separate class is referred to as a strategy. An object that uses a strategy object is often referred to as a context object.
In other words, Strategy pattern is used when we have multiple algorithms for a specific task and client decides the actual implementation to be used at runtime. Strategy pattern is also known as Policy pattern. We define multiple algorithms and let client application pass the algorithm to be used as a parameter. One of the best example of this pattern is Collections.sort() method that takes Comparator parameter. Based on the different implementations of Comparator interfaces, the objects are getting sorted in different ways.
The Strategy pattern is one way that composition can be used as an alternative to subclassing. Rather than providing different behaviors via subclasses overriding methods in super classes, the strategy pattern allows different behaviors to be placed in concrete strategy classes which share the common strategy interface. A context object contains a reference to a strategy. By changing the context's strategy, different behaviors can be obtained.
There are three participants in the Strategy pattern
Let's take a look at how some client might put the Strategy pattern into action.
When to use the Strategy design pattern
Java
Here is an example of the strategy pattern. First, we'll define a Strategy interface. It declares a checkTemperature() method.
File Strategy.java.
public interface Strategy {
boolean checkTemperature(int temperatureInF);
}
The HikeStrategy class is a concrete strategy class that implements the Strategy interface. The checkTemperature method is implemented so that if the temperature is between 50 and 90, it returns true. Otherwise it returns false.
File HikeStrategy.java.
public class HikeStrategy implements Strategy {
@Override
public boolean checkTemperature(int temperatureInF) {
if ((temperatureInF >= 50) && (temperatureInF <= 90)) {
return true;
} else {
return false;
}
}
}
The SkiStrategy implements the Strategy interface. If the temperature is 32 or less, the checkTemperature method returns true. Otherwise it returns false.
File SkiStrategy.java.
public class SkiStrategy implements Strategy {
@Override
public boolean checkTemperature(int temperatureInF) {
if (temperatureInF <= 32) {
return true;
} else {
return false;
}
}
}
The Context class contains a temperature and a reference to a Strategy. The Strategy can be changed, resulting in different behavior that operates on the same data in the Context. The result of this can be obtained from the Context via the getResult() method.
File Context.java.
public class Context {
int temperatureInF;
Strategy strategy;
public Context(int temperatureInF, Strategy strategy) {
this.temperatureInF = temperatureInF;
this.strategy = strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public int getTemperatureInF() {
return temperatureInF;
}
public boolean getResult() {
return strategy.checkTemperature(temperatureInF);
}
}
The Demo class creates a Context object with a temperature of 60 and with a SkiStrategy. It displays the temperature from the context and whether that temperature is OK for skiing. After that, it sets the Strategy in the Context to HikeStrategy. It then displays the temperature from the context and whether that temperature is OK for hiking.
File Demo.java.
public class Demo {
public static void main(String[] args) {
int temperatureInF = 60;
Strategy skiStrategy = new SkiStrategy();
Context context = new Context(temperatureInF, skiStrategy);
System.out.println("Is the temperature (" + context.getTemperatureInF() + "F) good for skiing? " + context.getResult());
Strategy hikeStrategy = new HikeStrategy();
context.setStrategy(hikeStrategy);
System.out.println("Is the temperature (" + context.getTemperatureInF() + "F) good for hiking? " + context.getResult());
}
}
Python 3
import abc
class Strategy(metaclass=abc.ABCMeta):
@abc.abstractmethod
def check_temperature(self, temperature):
pass
class HikeStrategy(Strategy):
def check_temperature(self, temperature):
if temperature >= 50 and temperature <= 90:
return True
else:
return False
class SkiStrategy(Strategy):
def check_temperature(self, temperature):
if temperature <= 32:
return True
else:
return False
class Context:
def __init__(self, temperature, strategy):
self.temperature = temperature
self.strategy = strategy
def set_strategy(self, strategy):
self.strategy = strategy
def get_temperature(self):
return self.temperature
def get_result(self):
return self.strategy.check_temperature(temperature)
if __name__ == '__main__':
temperature = 60
strategy_ski = SkiStrategy()
context = Context(temperature, strategy_ski)
print("Is the temperature ({} F) good for skiing? {}".format(context.get_temperature(), context.get_result()))
strategy_hike = HikeStrategy()
context.set_strategy(strategy_hike)
print("Is the temperature ({} F) good for hiking? {}".format(context.get_temperature(), context.get_result()))