What is Strategy Pattern?: Strategy is a behavioral design pattern that lets you define a family of algorithms, put each of them into a separate class, and make their objects interchangeable.
The Strategy pattern (aka the policy pattern) attempts to solve the issue where you need to provide multiple solutions for the same problem so that one can be selected at runtime.
Why Strategy Pattern?:
Sometime the code becomes complex if there are so many code behaviors included in the same class and it become hard for a new developer to fix it. Also if the team size is big, it also become tedious for multiple developers to work on single class which uses mix of codes. So in order to override this problem, we create separate classes which includes specific type of behavior instead of mix behavior and call them using strategy during runtime.
Problem: You need to provide a geographical-based search engine solution where the implementing code can choose the search provider at runtime.
geocode('test center')
//=> 37.7845456,-129.3994262
Solution:
public interface GeocodeStrategy{
List<Double> getLatLong(String address);
}
public class GoogleMapsStrategy implements GeocodeStrategy{
public List<Double> getLatLong(String address){
// Web service callout
return new List<Double>{0,0};
}
}
public class MapQuestStrategy implements GeocodeStrategy{
public List<Double> getLatLong(String address){
// Web service callout
return new List<Double>{1,1};
}
}
public class Geocoder {
public class GeocoderException extends Exception{}
public static final Map<String,GeocodeStrategy> strategies;
static{
// Populate a List Collection of strategy names e.g., googleMaps, mapQuest etc
List<String> strategyNames = Label.strategies.split(',');
// Populate a map of strategy names to concrete implementations
// using Type.forName for each strategy string
strategies = new Map<String,GeocodeStrategy>();
for(String name : strategyNames){
try{
strategies.put(name, (GeocodeStrategy)Type.forName(name + 'impl').newInstance());
} catch(Exception e){ //skip bad name silently
system.debug(e.getMessage());
}
}
}
private GeocodeStrategy strategy;
public Geocoder(String name){
if(!strategies.containsKey(name)) {
throw new GeocoderException(name);
}
strategy = strategies.get(name);
}
public List<Double> getLatLong(String address){
return strategy.getLatLong(address);
}
}
Geocoder geocoder = new Geocoder('googleMaps'); //It assigns instance of GoogleMapsStrategy to geocoder
System.debug('latitudes***' +
geocoder.getLatLong('test location1')); //It prints latitudes***(0.0, 0.0) in debug log
Geocoder geocoder = new Geocoder('mapQuest'); //It assigns instance of MapQuestStrategy to geocoder
System.debug('latitudes***' +
geocoder.getLatLong('test location1')); //It prints latitudes***(1.0, 1.0) in debug log
Let’s understand this code using below pictorial representation which is self explanatory-

The Strategy design pattern uses aggregation instead of inheritance, allowing better decoupling between the behavior and the class that uses the behavior. This allows the behavior to be changed without breaking the classes that use it, and the classes can switch between behaviors by changing the specific implementation used without requiring any significant code changes.
For all Design Patterns, please refer this.
Wonderful article. Fascinating to read. I love to read such an excellent article. Thanks! It has made my task more and extra easy. Keep rocking.