Java strategy pattern in functional programming
What is Strategy pattern :
Software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives runtime instructions as to which in a family of algorithms to use.
Declarative Programming
Prior to functional programming, Java used imperative programming. Imperative programming is a software development paradigm that expresses commands. In imperative programming, each operation is coded, and the code specifies how to solve a problem.
Java developers came up with an idea of declarative programming where we specify what you want to achieve . Do not specify how to implement an operation.
Below code illustrates how to filter products using imperative approach, then declarative approach and finally convert it into functional programming.
Code Illustration
public class Product {
private int productCode;
private String name;
private String category;
private int price;
// getters and setters
}
// Service class
public List<String> getLowPriceMobile_v1(List<Product> products){
List<String> lowPriceMobiles = new ArrayList<>();
for(Product product : products){
boolean lowPrice = filterByLowPriceOrMobile_v1(product,"price");
boolean isMobile = filterByLowPriceOrMobile_v1(product,"category");
if(lowPrice && isMobile){
lowPriceMobiles.add(mapToProductName(product));
}
}
return lowPriceMobiles;
}
public List<String> getLowPriceMobile_v2(List<Product> products){
List<String> lowPriceMobiles = new ArrayList<>();
for(Product product : products){
boolean lowPrice = filterByLowPriceOrMobile_v2(product,new ProductFilterByPriceImpl());
boolean isMobile = filterByLowPriceOrMobile_v2(product,new ProductFilterByMobileImpl());
if(lowPrice && isMobile){
lowPriceMobiles.add(mapToProductName(product));
}
}
return lowPriceMobiles;
}
/**
* Lambda expression : Anonymous function
*/
public List<String> getLowPriceMobile_v3(List<Product> products){
List<String> lowPriceMobiles = products.stream().filter(product -> (product.getPrice() < 5000)).
filter(product -> (product.getCategory().equals("Mobile"))).
map(product -> product.getName()).collect(Collectors.toList());
return lowPriceMobiles;
}
/**
* Behaviour parameterization
* Strategy pattern : Software design pattern that enables selecting an algorithm at runtime.
* Instead of implementing a single algorithm directly, code receives runtime instructions
* as to which in a family of algorithms to use.
*/
public boolean filterByLowPriceOrMobile_v2(Product product, ProductFilterService productFilterService){
return productFilterService.filter(product);
}
public boolean filterByLowPriceOrMobile_v1(Product product,String filterType){
boolean result = false;
if(filterType.equals("price")){
if(product.getPrice()<10000){
result = true;
}
} else if(filterType.equals("category")) {
if(product.getCategory().equals("Mobile")){
result = true;
}
}
return result;
}
public String mapToProductName(Product product){
return product.getName();
}
public List<Product> createProducts(){
List<Product> products = new ArrayList<>();
products.add(new Product(101,"I-Phone","Mobile",70000));
products.add(new Product(102,"Redmi","Mobile",9000));
products.add(new Product(501,"Basketball","Sport",1200));
products.add(new Product(502,"Football","Sport",1800));
return products;
}