Factory Design Pattern is one of the Creational Design pattern and it’s widely used in JDK as well as frameworks like Spring MVC and Struts. 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. The Factory method lets a class defer instantiation to subclasses“.
Let’s first learn how to implement factory pattern in java. We will create 5 classes to implement this pattern.
- Super Class (CrunchfiyCompany.java)
- Super class in factory pattern can be an interface, abstract class or a normal java class. For our example, we have super class as abstract class with overridden
toString()
method for testing purpose.
- Super class in factory pattern can be an interface, abstract class or a normal java class. For our example, we have super class as abstract class with overridden
- Sub Class1 (CrunchifyEbay.java)
- Notice that the class is extending CrunchfiyCompany class.
- Sub Class2 (CrunchifyGoogle.java)
- Notice that the class is extending CrunchfiyCompany class.
- Factory Class (CrunchifyFactoryPattern.java)
- Now that we have super classes and sub-classes ready, we can write our factory class.
- We can keep Factory class Singleton or we can keep the method that returns the subclass a static.
- Notice that based on the input parameter, different subclass is created and returned.
- Test Class (CrunchifyFactoryPatternTest.java)
- Simple Test client program that uses above factory pattern implementation.
Other must reads:
- Thread-Safe and a Fast Singleton Implementation in Java
- What is Daemon Thread in Java? Example Attached
package com.crunchify.tutorials; /** * @author Crunchify.com */ // Super class in factory pattern can be an interface, abstract class or a // normal java class. For our example, we have super class as abstract class // with overridden toString() method for testing purpose. public abstract class CrunchfiyCompany { public abstract String getPhoneNumber(); public abstract String getZipCode(); @Override public String toString() { return "Phone #= " + this.getPhoneNumber() + ", Zip Code= " + this.getZipCode(); } }
package com.crunchify.tutorials; /** * @author Crunchify.com */ // Notice that the class is extending CrunchfiyCompany class. public class CrunchifyEbay extends CrunchfiyCompany { private String phoneNumber; private String zipCode; public CrunchifyEbay(String phoneNumber, String zipCode) { this.phoneNumber = phoneNumber; this.zipCode = zipCode; } @Override public String getPhoneNumber() { return this.phoneNumber; } @Override public String getZipCode() { return this.zipCode; } }
package com.crunchify.tutorials; /** * @author Crunchify.com */ // Notice that the class is extending CrunchfiyCompany class. public class CrunchifyGoogle extends CrunchfiyCompany { private String phoneNumber; private String zipCode; public CrunchifyGoogle(String phoneNumber, String zipCode) { this.phoneNumber = phoneNumber; this.zipCode = zipCode; } @Override public String getPhoneNumber() { return this.phoneNumber; } @Override public String getZipCode() { return this.zipCode; } }
package com.crunchify.tutorials; import com.crunchify.tutorials.CrunchfiyCompany; import com.crunchify.tutorials.CrunchifyEbay; import com.crunchify.tutorials.CrunchifyGoogle; /** * @author Crunchify.com */ // Now that we have super classes and sub-classes ready, we can write our factory class. // We can keep Factory class Singleton or we can keep the method that return the subclass a static. // Notice that based on the input parameter, different subclass is created and returned. public class CrunchifyFactoryPattern { public static CrunchfiyCompany getDetails(String type, String phoneNumber, String zipCode) { if ("Ebay".equalsIgnoreCase(type)) return new CrunchifyEbay(phoneNumber, zipCode); else if ("Google".equalsIgnoreCase(type)) return new CrunchifyGoogle(phoneNumber, zipCode); return null; } }
package com.crunchify.tutorials; import com.crunchify.tutorials.CrunchfiyCompany; import com.crunchify.tutorials.CrunchifyFactoryPattern; /** * @author Crunchify.com */ // Simple Test client program that uses above factory pattern implementation. public class CrunchifyFactoryPatternTest { public static void main(String[] args) { CrunchfiyCompany eBay = CrunchifyFactoryPattern.getDetails("Ebay", "408.123.4567", "98765"); CrunchfiyCompany google = CrunchifyFactoryPattern.getDetails("Google", "519.123.4567", "56789"); System.out.println("Factory eBay Config::" + eBay); System.out.println("Factory Google Config::" + google); } }
Factory eBay Config::Phone #= 408.123.4567, Zip Code= 98765 Factory Google Config::Phone #= 519.123.4567, Zip Code= 56789
Other Examples using Factory Pattern?
- java.util.Calendar, ResourceBundle and NumberFormat
getInstance()
methods uses Factory pattern. valueOf()
method in wrapper classes like Boolean, Integer etc.
Benefits of Factory Pattern:
- It is used when we have a super class with multiple sub-classes and based on input, we need to return one of the sub-class. This pattern take out the responsibility of instantiation of a class from client program to the factory class.
- Factory pattern provides approach to code for interface rather than implementation.
- Factory pattern removes the instantiation of actual implementation classes from client code, making it more robust, less coupled and easy to extend. For example, we can easily change PC class implementation because client program is unaware of this.
- Factory pattern provides abstraction between implementation and client classes through inheritance.
Drawbacks:
- The factory has to be used for a family of objects. If the classes doesn’t extend common base class or interface they can not be used in a factory design template.
List of all Java Web Development, Spring MVC tutorials.