Tuesday, March 25, 2014

GOF Design Patterns in Java - Factory Method Pattern

GOF Design Patterns in Java - Factory Method Pattern


For this Design pattern, I will discuss all below sections
Case Study Requirements  9 – Case study Requirement to demonstrate GOF design Patter
Naive Implementation Proposal 9 – Naïve Implementation for above case study without GOF design Pattern
Naïve Code Example  9 – Code example with above proposal
Limitations in above approach  9 –Limitations with above approach
Definition  9 – definition as of Gang of Four
Overview   10 – Brief about the design pattern with suitable realtime example
Structure  10 – class/flow diagram as per GOF
Code Example – code example by applying Patter
Benefits and Liabilities  11 – Advantages and disadvantages with this pattern
Points to Remember  11 – Points to remember
When to use – where and when this pattern will be applicable
Example from Java API 12 – Known example from java api

Case Study Requirements

I have electronic show room I sell Samsung machines and Refrigerators.
I need an application that can show details of all my Samsung machines whenever I want.

Naive Implementation Proposal




Naive Code Example

public class ProductDetails {

       public RefrigeratorDetails getSamsungRefrigeratorDetails() {
              RefrigeratorDetails samsungFrige = new RefrigeratorDetails() ;
              samsungFrige.setColor("White Blue");
              samsungFrige.setModelNo("Samsung Refreegerator WB001");
              samsungFrige.setCpacity("6 Leter");
              samsungFrige.setPrice("15000");
              return samsungFrige ;
       }
      
       public WashingMachineDetails getSamsungWashingMachineDetails() {
              WashingMachineDetails samsungWS  = new WashingMachineDetails() ;
              samsungWS.setColor("White Blue");
              samsungWS.setModelNo("Samsung washing machine model BW001");
              samsungWS.setCapacity("6 kg");
              samsungWS.setPrice("20000");
              return samsungWS ;
       }
      
      
}


public class RefrigeratorDetails {

       String modelNo , cpacity , price, color ;
//setter getter

}

public class WashingMachineDetails {
      
         String modelNo , capacity , price, color ;

            //setter getter
}

public class Client {

        public static void main(String[] args) {
               
               ProductDetails productDetails = new ProductDetails();
               WashingMachineDetails washingMachine = productDetails.getSamsungWashingMachineDetails();
               System.out.println(washingMachine.getCapacity());
               System.out.println(washingMachine.getModelNo());
               System.out.println(washingMachine.getColor());
               System.out.println(washingMachine.getPrice());
             
       }
}

Limitations in above approach


  1.            If washing Machine, refrigerator Details are provided by third party In future, then this application will not work. 
  2. Client is directly dealing with actual implementation that means client is tightly coupled due to that if any product name is changed we need to change the calling method name. In our example we are accessing productDetails.getSamsungWashingMachineDetails() In future if you want to get other product details you need to call some other method like productDetails.getSamsungRefrigeratorDetails which is huge change at client side.
  3. Different methods returning different types of objects so cannot provide a generic way to handle objects at client side.
  4. ProductDetails class size will be increased if new product is introduced that effects the readability of the class.



Definition

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

Overview

Every Framework supports their services to developers with the help of set of abstract classes and Interfaces. These abstract classes are being implemented by the developers. But in beforehand framework designer do not have idea that how these objects are going to be created by Framework users. Handling these kinds of objects is really difficult to the Framework designer. This kind problem can be solved with the help of Factory Method design pattern.

Structure


   Code Example


public interface ProductDetails {

       public String getModelNo();

       public String getPrice();

       public String getColor();

       public String getCapacity();

       public void setColor(String color);

       public void setModelNo(String modelNo);

       public void setCapacity(String capacity);

       public void setPrice(String price);

}

 

public class ProductFactory extends ProductFactoryCreator {

       protected <T extends ProductDetails> T getProductFactory(Class<T> clazz) {

              T samsungWS = null;
              try {
                     samsungWS = clazz.newInstance();
                     samsungWS.setModelNo("Samsung washing machine model WWBW001");
                     samsungWS.setCapacity("6 kg");
                     samsungWS.setPrice("20000");
                    
              } catch (InstantiationException e) {
                     e.printStackTrace();
              } catch (IllegalAccessException e) {
                     e.printStackTrace();
              }
              return samsungWS;
       }
      
}

public abstract class ProductFactoryCreator {
       protected abstract <T extends ProductDetails> T getProductFactory (Class<T> clazz);
      
}

public class RefrigeratorDetails implements ProductDetails {

       String modelNo , capacity , price, color ;
//setter getter
}

public class WashingMachineDetails implements ProductDetails {
      
         String modelNo , capacity , price, color ;

         //setter getter
}

Benefits and Liabilities
  1. Client is not directly dealing with actual implementations so it is loosely coupled with actual implementation.  Since all products are expected to be implemented ProductDeatils, if product is changed no huge change will be at client side.
  2. Since all products are implementing all products will have same so developer can provide a generic way to handle objects at client side.
  3. Adding new product is easy. Just implementing the interface ProductDeatils is enough.
  4. Factory method provides the facility to subclass to implement how they want.

Points to Remember

Java Static Factory Methods are different to GOF Factory Method design pattern.
You can also apply generics for bounded parameters. But it has its own limitations. If your application is “Ok” with those you can use as shown below
protected <T extends ProductDetails> T getProductFactory(Class<T> clazz) {

              T samsungWS = null;
              try {
                     samsungWS = clazz.newInstance();
                     samsungWS.setModelNo("Samsung washing machine model WWBW001");
                     samsungWS.setCapacity("6 kg");
                     samsungWS.setPrice("20000");
                    
              } catch (InstantiationException e) {
                     e.printStackTrace();
              } catch (IllegalAccessException e) {
                     e.printStackTrace();
              }
              return samsungWS;
       }



When to use


  1. When the implementation details are not known at development time i.e., Concrete implementation is being provided by others who will use our class in future.
  2.  When a super class wants specify the object that are going to be created by subclass

Example from Java API



No comments:

Post a Comment