Thursday, February 13, 2014

Factory method Design Pattern in Java

In this post, we'll see how Factory method Design Pattern come into picture, what advantages it will provide and how it help in implementing loose coupling concept.

Below picture shows Car factory that produce different car depending on it's feature and model. For instance, it produces BMW 1 series, BMW 2 Series, BMW M3 etc. Whatever order we placed for car, factory will produce.

This same concept applies to Factory Design pattern.




From the name itself you can identify what does this pattern do. Factory method pattern is used for creating object based on different parameters. If we ask for BMW M3, the factory will produce BMW M3; if we ask for Ferrari, factory will produce Ferrari.

The factory method pattern is an object-oriented creational design pattern to implement the concept of factories and deals with the problem of creating objects (products) without specifying the exact class of object that will be created. The essence of this pattern is to "Define an interface for creating an object, but let the classes that implement the interface decide which class to instantiate.


How Factory Design pattern come into picture
When you use "new" you are certainly instantiating a concrete class, so that's is definitely an implementation, not an interface. Typing a code to a concrete class can make it more fragile and less flexible. How? let's see an example

interface Car{  
      void paintColor(String color);  
 }  
 class BMW implements Car{  
      @Override  
      public void paintColor(String color) {  
           System.out.println("Red");  
      }  
 }  
 class Ferrari implements Car{  
      @Override  
      public void paintColor(String color) {  
           System.out.println("Green");  
      }  
 }  
 class Audi implements Car{  
      @Override  
      public void paintColor(String color) {  
           System.out.println("Yellow");  
      }  
 }  
 public class CreateCar {  
      Car createCar(String carType){  
           Car c = null;  
           if(carType.equals("Audi")){  
                c = new Audi();  
           }else if(carType.equals("BMW")){  
                c = new BMW();  
           }else if(carType.equals("Ferrari")){  
                c = new Ferrari();  
           }  
           return c;  
      }  
 }

Here we have got several class being instantiated and the decision of which to instantiate is made at run time depending on condition.
When it comes time for change or extensions  you'll need to open this code and examine what need to be added or deleted. This kind of code ends up in several part of the application making maintenance and update more difficult.

By coding to interface, you can free yourself from a lot of changes that might happen to a system down the road. How? 
If your code is written to interface, then it work with any new class implementing that interface through polymorphism. But, when you have code that make a lot of concrete class, you are looking for trouble because that code may have to changed as new concrete classed are added. It means this code is not "closed for modification".

public class PreFactoryPatternDemo {  
      Car createCar(String carType){  
           Car c = null;  
           if(carType.equals("Audi")){  
                c = new Audi();  
           }else if(carType.equals("BMW")){  
                c = new BMW();  
           }else if(carType.equals("Ferrari")){  
                c = new Ferrari();  
           }else if(carType.equals("volkswagen")){  
                c = new Ferrari();  
           }else if(carType.equals("chevrolet")){  
                c = new Ferrari();  
           }else if(carType.equals("hyundai")){  
                c = new Ferrari();  
           }else if(carType.equals("Maruti")){  
                c = new Ferrari();  
           }  
           return c;  
      }  
 }

Now here come the first design principle : identify the aspects that vary and separate them from what stays the same.
But now we know that what is varying and what isn't, it's probably time to encapsulate it.

Encapsulating Object creation
We will move the following code out, then place that code in an object that is only going to worry about how to create car. If anybody object need a car object created, this is object to come in.

Car c;  
           if(args[0].equals("Audi")){  
                c = new Audi();  
           }else if(args[0].equals("BMW")){  
                c = new BMW();  
           }else if(args[0].equals("Ferrari")){  
                c = new Ferrari();  
           }else if(args[0].equals("volkswagen")){  
                c = new Ferrari();  
           }else if(args[0].equals("chevrolet")){  
                c = new Ferrari();  
           }else if(args[0].equals("hyundai")){  
                c = new Ferrari();  
           }else if(args[0].equals("Maruti")){  
                c = new Ferrari();  
           }  

We got a name for this new object; we call it a Factory.
Now our code look like
 class CarFactory{  
      public Car defaultCar(String type){  
           Car c = null;   
           if(type.equals("Audi")){   
                c = new Audi();   
           }else if(type.equals("BMW")){   
                c = new BMW();   
           }else if(type.equals("Ferrari")){   
                c = new Ferrari();   
           }else if(type.equals("volkswagen")){   
                c = new Ferrari();   
           }else if(type.equals("chevrolet")){   
                c = new Ferrari();   
           }else if(type.equals("hyundai")){   
                c = new Ferrari();   
           }else if(type.equals("Maruti")){   
                c = new Ferrari();   
           }   
           return c;   
      }  
 }

It looks like we are just pushing the problem off to another object. Yes, you are right. One thing to remember is that CarFactory may have different client.
We have only seen the createCar method; however, there may be different class TyreCar that uses the factory to get car for tunning tyre performance.
We might also have a EngineCar class that tune the engine other than CreateCar. So TyreCar, EngineCar also need instance of car instead of writing the object creation each class, they are use Factory class.

Final Code will look like

interface Car{  
      void setPaint(String color);  
      void setEngine(String engine);  
      void setTyre(String tyre);  
 }  
 class Audi implements Car{  
      public void setPaint(String color) {  
           System.out.println("Black color for Audi");  
      }  
      public void setEngine(String engine) {  
           System.out.println("1000cc Engine for Audi");  
      }  
      public void setTyre(String tyre) {  
           System.out.println("Apollo tyre for Audi");  
      }  
      public String toString(){  
           return "Black Audi with 1000c";  
      }  
 }  
 class BMW implements Car{  
      public void setPaint(String color) {  
           System.out.println("Red color for BMW");  
      }  
      public void setEngine(String engine) {  
           System.out.println("800cc Engine for BMW");  
      }  
      public void setTyre(String tyre) {  
           System.out.println("Apollo tyre for BMW");  
      }  
      public String toString(){  
           return "Red BMW with 800cc";  
      }  
 }  
 class Ferrari implements Car{  
      public void setPaint(String color) {  
           System.out.println("Yello color for Ferrari");  
      }  
      public void setEngine(String engine) {  
           System.out.println("1800cc Engine for Ferrari");  
      }  
      public void setTyre(String tyre) {  
           System.out.println("Apollo tyre for Ferrari");  
      }       
      public String toString(){  
           return "Yello Ferrari with 1800cc";  
      }  
 }  
 class CarFactory{  
      public static Car defaultCar(String name){  
           Car c = null;  
           if(name.equals("Audi")){  
                c = new Audi();  
           }else if(name.equals("BMW")){  
                c = new BMW();  
           }else if(name.equals("ferrari")){  
                c = new Ferrari();  
           }  
           return c;  
      }  
 }  
 public class a{  
      public static void main(String javalatte[]){  
           Car c;  
           c = CarFactory.defaultCar("Audi");  
           c.setTyre("BridgeStone");  
           c = CarFactory.defaultCar("BMW");  
      }  
 }



  • Factory patterns are examples of creational patterns.
  • Creational patterns abstract the object instantiation process.They hide how objects are created and help make the overall system independent of how its objects are created and composed.
  • Class creational patterns focus on the use of inheritance to decide the object to be instantiated -Factory Method
All OO languages have an idiom for object creation. In Java this idiom is the new operator. Creational patterns allow us to write methods that create new objects without explicitly using the new operator. This allows us to write methods that can instantiate different objects and that can be extended to instantiate other newly-developed objects, all without modifying the method's code!


Applicability
  • A class can't anticipate the class of objects it must create
  • A class wants its subclasses to specify the objects it creates
Factory design pattern used in Java standard library

Based on different parameter, getInstance() returns a different instance of Calendar
java.util.Calendar – getInstance()
java.util.Calendar – getInstance(TimeZone zone)
java.util.Calendar – getInstance(Locale aLocale)
java.util.Calendar – getInstance(TimeZone zone, Locale aLocale)

java.text.NumberFormat – getInstance()
java.text.NumberFormat – getInstance(Locale inLocale)




If you know anyone who has started learning Java, why not help them out! Just share this post with them. 
Thanks for studying today!...

No comments:

Post a Comment