Refactoring Factory Design Pattern with Lambdas

Many existing object-oriented design patterns can be made redundant or written in a more concise way using lambda expressions.
In this post, I would like to explain how to refactor the Factory Design Pattern using lambda expressions?. This post may help in some situations like if we have implemented Factory Pattern in our projects using JDK 6 or 7.
Now we want to use JDK 8 then we can refactor implementation of Factory Design Pattern using lambda expressions or we newly implement Factory Design Pattern using lambda expressions in our projects.

Let's understand this refactoring technique with a detailed example.

If you are new to Factory Pattern then there is a separate post for you: Factory Design Pattern.
If you want to revise or read the lambda expressions then visit lambda expressions.
As we know the Factory Design Pattern lets us create objects without exposing the instantiation logic to the client. For example, let’s say you’re working for a bank and they need a way of creating different financial products: loans, bonds, stocks, and so on.
Let's draw a class diagram and write some code to understand Factory Design Pattern and then use a lambda expression to remove boilerplate code.

Factory Design Pattern: Without Using Lambda Expressions

Typically we create a Factory class with a method that’s responsible for the creation of different objects, as shown here :
public class FactoryMain {
    public static void main(String[] args) {
        Product p1 = ProductFactory.createProduct("loan");

    }
}
public class ProductFactory {
        public static Product createProduct(String name){
            switch(name){
                case "loan": return new Loan();
                case "stock": return new Stock();
                case "bond": return new Bond();
                default: throw new RuntimeException("No such product " + name);
            }
        }

    }

    static private interface Product {}
    static private class Loan implements Product {}
    static private class Stock implements Product {}
    static private class Bond implements Product {}

}
Here, Loan, Stock, and Bond are all subtypes of Product. The createProduct() method could have additional logic to configure each created product. But the benefit is that you can now create these objects without exposing the constructor and the configuration to the client, which makes the creation of products simpler for the client:
Product p = ProductFactory.createProduct("loan");

Factory Design Pattern: Using Lambda Expressions

We can refer to constructors just like you refer to methods, by using method references. For example, here’s how to refer to the Loan constructor:
Supplier<Product> loanSupplier = Loan::new;
Loan loan = loanSupplier.get();
Using this technique, you could rewrite the previous code by creating a Map that maps a product name to its constructor:
  private final static Map<String, Supplier<Product>> map = new HashMap<>();    static {
        map.put("loan", Loan::new);
        map.put("stock", Stock::new);
        map.put("bond", Bond::new);
    }
Let's use this Map to instantiate different products, just as you did with the factory design pattern:
public static Product createProductLambda(String name){
       Supplier<Product> p = map.get(name);
       if(p != null) return p.get();
       throw new RuntimeException("No such product " + name);}

Related posts


Comments