Writing readable and extendable code is magic. Be a magician. Anonymous (jk. It's me)
Strategy pattern
The strategy pattern helps to decide which algorithm to use during runtime thus giving more reusability and extensibilty.Problem:
You have a problem where you can solve it using different algorithms and you need to choose which one to use depending on the input from the client, you can go for Strategy pattern.Example 1:
You are giving offers in your ticket booking site based on the current month.
Example 2:
You are compressing a file and you need to decide the format during runtime.
Example 3:
You are implementing a login feature for your product and you need to enable login with different service providers like google, facebook, github and so on.
Example 4:
You are implementing various payment methods like COD, paypal, UPI, etc in your product website. How it can be solved using Strategy pattern? In strategy pattern, 3 different components gets involved excluding the Client.
- Context class
- Strategy interface
- Different Strategy implementations
-> Context class
This class will be the single point of contact to the client. Context class isn't responsible for choosing any strategy, the client chooses them and sets them to the context. Usually context allows strategy as a constructor or/and a setter method, so runtime can be handled effectively.-> Strategy interface
The interface which needs to be implemented by all the algorithms which wishes to be interchangable.-> Strategy implementation class
These classes implement the Strategy interface and they will be interchangable during runtime.Design Structure
photo courtesy: link
Sample code
import java.util.Scanner;
interface DiscountStrategy {
public Double getDiscountPercentage();
}
class HolidaysDiscountStrategy implements DiscountStrategy{
public Double getDiscountPercentage() {
return 0.4;
}
}
class NoDiscountStrategy implements DiscountStrategy{
public Double getDiscountPercentage() {
return 0.0;
}
}
class PurchaseStrategyContext { // Context acts as a single point of contact for the clients.
Double cost;
DiscountStrategy discountStrategy;
public PurchaseStrategyContext(Double cost) {
this.cost = cost;
discountStrategy = new NoDiscountStrategy();
}
public DiscountStrategy getDiscountStrategy(int monthNumber) {
if(monthNumber > 10 && monthNumber <=12) {
return new HolidaysDiscountStrategy();
} else {
return new NoDiscountStrategy();
}
}
public void applyDiscountStrategy(DiscountStrategy strategy) {
this.discountStrategy = strategy;
}
public Double getCost() {
return (this.cost - (this.discountStrategy.getDiscountPercentage() * this.cost));
}
}
public class StrategyPattern {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the cost of the cart");
Double costOfTheCart = sc.nextDouble();
System.out.println("Enter the current month");
int currentMonth = sc.nextInt();
PurchaseStrategyContext context = new PurchaseStrategyContext(costOfTheCart);
DiscountStrategy strategy = context.getDiscountStrategy(currentMonth); //Get can be done here or strategy can be initialized here
context.applyDiscountStrategy(strategy);
Double finalPrice = context.getCost();
System.out.println("The final cost after the discount is " + finalPrice);
}
}
As seen in the code, the respective discount strategies can be set at runtime depending on the client's input. Suppose if we need to add a new discount strategy, we just need to write a class implementing the Strategy interface and that's it. If client set the new strategy to the context, it will work as smooth as butter.
Thank you. Hope this helps. Looking forward to more learnings and sharings. Cheers :)