Sunday 18 May 2014

Factory Design Pattern



Factory Design Pattern:
               This pattern is to create the number of objects as per request with the help of polymorphism and inheritance (super-class-sub-class). Creation of object is generally getting decided using String pattern. This pattern allows creating the object without exposing the instantiation logic.
Let us see the example below for Shoes factory which is able to create n number of objects as per request:-
1st Approach:-
public class MyShoesFactory {
      private MyShoesFactory(){}

      public static Shoes createShoesObject(String shoesType){
           
            if("Sports".equals(shoesType)){
                  return new SportShoes();
            }
            if("Formal".equals(shoesType)){
                  return new SportShoes();
            }
            if("Casual".equals(shoesType)){
                  return new SportShoes();
            }    
            return null;
      }
}


interface Shoes{
     
}


class SportShoes implements Shoes{
      //code here
}


class FormalShoes implements Shoes{
      //code here
}


class CasualShoes implements Shoes{
      //code here
}

2nd Approach:-
Better design, no need to change the MyShoesFactory class, used reflection and tried to keep open/closed principal implemented nicely.

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;

public class MyShoesFactory {

      private MyShoesFactory(){}

      @SuppressWarnings("unchecked")
      private static HashMap<String, Class> registeredShoesMap = new HashMap<String, Class>();    
     
      static{
            MyShoesFactory.registerShoes("Formal", FormalShoes.class);
            MyShoesFactory.registerShoes("Casual", CasualShoes.class);
            MyShoesFactory.registerShoes("Sport", SportShoes.class);
      }

      @SuppressWarnings("unchecked")
      public static void registerShoes(String shoesId, Class shoesClass)      {
            registeredShoesMap.put(shoesId, shoesClass);   
      }    

      @SuppressWarnings("unchecked")
      public static Shoes createShoesObject(String shoesID) throws SecurityException,
      NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException      {

            Class shoesClass = (Class)registeredShoesMap.get(shoesID); 
            Constructor shoesConstructor = shoesClass.getDeclaredConstructor();     
            return (Shoes)shoesConstructor.newInstance(new Object[] { });     
      }
}

interface Shoes{

      public void displayMessage();
}

class SportShoes implements Shoes{
     
      //code here
      public void displayMessage(){
            System.out.println(" I am a Sport Shoes ... ");
      }
}

class FormalShoes implements Shoes{
     
      //code here
      public void displayMessage(){
            System.out.println(" I am a Formal Shoes ... ");
      }
}

class CasualShoes implements Shoes{
     
      //code here
      public void displayMessage(){
            System.out.println(" I am a Casual Shoes ... ");
      }
}

import java.lang.reflect.InvocationTargetException;

public class Client {

      public static void main(String[] args) throws SecurityException, IllegalArgumentException,
            NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
                       
            Shoes formalShoes = MyShoesFactory.createShoesObject("Formal");
            Shoes casualShoes = MyShoesFactory.createShoesObject("Casual");
            formalShoes.displayMessage();
            casualShoes.displayMessage();
      }
}
Output:
 I am a Formal Shoes ...
 I am a Casual Shoes ...

If any new type of shoes comes in future (say FashionShoes) no need to modify the factory class just use the below snippet in Client class to register FashionShoes class with Factory:

MyShoesFactory.registerShoes("Fashion", FashionShoes.class);

Use:-
Suppose if we are developing an application using Postgres database, but in future may need to change database to oracle, and then need to modify all our code, if not properly designed. One way to do this in better way is factory design pattern. A class implementing factory design pattern takes care for this and lessen the burden. Switching from database server won’t bother at all. We just need to make some small changes in our configuration file.
Note:-
               Factory design pattern should be used for a family of objects. If the classes don’t extend/implement common base class/interface they can not be used.

No comments:

Post a Comment