Factory Design Pattern In Java Factory Design Pattern In Java

Page content

Factory Design Pattern is one of the most commonly used design patterns. It falls under the category of Creational Design Patterns.

Overview

Analogy

As the name suggests, Factory Design Pattern is based on real time Factory concept. As we know that factory manufactures products as per the requirements. It does not expose the internal details of manufacturing. Also, in case of requirements for newer products, it manufactures them as well.

Similarly, Factory Design Pattern enables us to create objects using a factory class without exposing the creation logic to the client and thus providing abstraction with flexibility to extension.

When a client needs an object it asks the factory for it by providing some information on the type of object it requires. Factory method in factory class acts as a single place to create the objects from concrete classes based on the client’s input and return them as objects of interface or abstract types.

Virtual Constructor

This pattern replaces the direct object construction calls (using new operator) from client with calls to factory method. Since it replaces direct constructor calls, it is also known as Virtual Constructor.

GoF Design Patterns

According to GoF (Gangs of Four) Design Patterns,

Factory Design Pattern defines an interface for creating an object, but let subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.

When to use Factory Design Pattern?

  1. When we need to create objects of types which may be sub-classed.
  2. When client needs to create an object based on some input parameter and need not know how the object is created
  3. Also, a good choice when we don’t know the exact types before hand when starting on a project. This would provide ease to extensibility.

How to implement Factory Design Pattern?

  1. Create a super class (an interface)
  2. Create sub class(es) (requirement based):
    • Concrete A
    • Concrete B
    • Concrete C
  3. Factory Class with factory method that accepts some input parameter (to decide the type of object) to return the required object as object of interface
  4. Create an Enum that would be used to define types based on which factory method would create an object of concrete class
  5. Client code(main class) which creates an object using factory method of factory class by providing some input parameter and then use it

Code Example

Now we know what are the classes required to build a Factory Design Pattern.

Factory Design Pattern in Java
  1. Let’s first create an interface named Currency

    public interface Currency {
    
      String getCode();
      String getSign();
    
    }
    
  2. Create concrete classes Rupee, SGDollar, and USDollar implementing Currency interface

    public class Rupee implements Currency {
    
      @Override
      public String getCode() {
        return "INR";
      }
    
      @Override
      public String getSign() {
        return "₹";
      }
    }
    
    public class SGDollar implements Currency {
    
      @Override
      public String getCode() {
        return "SGD";
      }
    
      @Override
      public String getSign() {
        return "S$";
      }
    }
    
    public class USDollar implements Currency {
    
      @Override
      public String getCode() {
        return "USD";
      }
    
      @Override
      public String getSign() {
        return "$";
      }
    }
    
  3. Create an Enum Country for input parameter to factory method

    public enum Country {
    
      INDIA,
      SINGAPORE,
      USA,
      CANADA
    
    }
    
  4. Finally create a factory class CurrencyFactory

    public class CurrencyFactory {
    
      public static Currency createCurrency(String country) {
    
        if(country.equalsIgnoreCase(Country.SINGAPORE.toString())) {
          return new SGDollar();
        } else if(country.equalsIgnoreCase(Country.INDIA.toString()) {
          return new Rupee();
        } else if(country.equalsIgnoreCase(Country.USA.toString())) {
          return new USDollar();
        }
        throw new IllegalArgumentException(String.format("No currency found for '%s'", country));
      }
    
    }
    
  5. Let’s create a Client (Main Class) to test our Factory

    public class Client {
    
      public static void main(String [] args) {
    
        Currency indiaCurrency =
            CurrencyFactory.createCurrency(Country.INDIA.toString());
    
        Currency singaporeCurrency =
            CurrencyFactory.createCurrency(Country.SINGAPORE.toString());
    
        Currency usaCurrency =
            CurrencyFactory.createCurrency(Country.USA.toString());
    
        //Currency canadaCurrency = CurrencyFactory.createCurrency(Country.CANADA.toString());     
        //Exception in thread "main" java.lang.IllegalArgumentException: No currency found for 'CANADA'
    
        System.out.println(indiaCurrency.getCode());
        System.out.println(indiaCurrency.getSign());
    
        System.out.println(singaporeCurrency.getCode());
        System.out.println(singaporeCurrency.getSign());
    
        System.out.println(usaCurrency.getCode());
        System.out.println(usaCurrency.getSign());
      }
    }
    
    Output
    INR ₹ SGD S$ USD $

Advantages of Factory Design Pattern

  1. Loose Coupling: Introduces loose coupling between classes. Hence, involves programming against abstract entities rather than concrete implementations.
  2. Encapsulation: Good approach to encapsulation. Factory method used to create different objects from factory encapsulates the object creation code.
  3. Abstraction: Provides abstraction between implementation and client classes through inheritance.
  4. Single Responsibility Principle: Object creation is done at one place and this separates out the object creation code from actual usage. Any changes in object creation in future would require change in only place.
  5. Open/Closed Principle: Further to extend the functionality of factory to support newer type would be a small change i.e. adding a new subclass and corresponding object creation logic in factory method.