Factory Method vs. Simple Factory
They're easy to mix up, but it's critical to get Factory methods and Simple Factories right. Know when to apply each to make sure you're crushing your business reqs.
Join the DZone community and get the full member experience.
Join For FreeWhen interviewing a senior developer, my favorite question is, "Do you know design patterns?"
Obviously, the answer is always yes, so then I ask them about the design patterns they are familiar with and use in their projects?
In most cases, I get "Factory" and "Singleton."
As this is an article on the Factory Pattern, we'll ignore the Singleton interview discussion here.
The next question from my side is, "Tell me a business case and write down code fragments for the Factory method."
But unfortunately, I often get back the example of Shape — a well-known example found on Google — and they end up writing a Simple Factory, which is not considered a Design pattern.
In this article, I will not show how to write the Simple Factory and Factory methods. Rather, I prefer to discuss what are they and when to use them.
After taking enough interviews, I realized some points:
We are actually trying to memorize design patterns, not understand the problem it tries to solve.
Another realization is that we fail to analyze the business justification and apply patterns based on them. Rather, we try to find where we can fit the pattern that I know into the business case.
Simple Factory
/**
*
*/
package com.example.factory;
/**
* @author Shamik Mitra
*
*/
public interface ITV {
public void createTV();
}
-------------------------------
SimpleFactory.java
------------------------
/**
*
*/
package com.example.factory;
/**
* @author Shamik Mitra
*
*/
public class TVSimpleFactory {
enum TVMODE{COLOR,LED,LCD,THREEDIM};
public static ITV getTV(TVMODE mode){
if(mode.equals(TVMODE.LED)){
return new ITV(){
@Override
public void createTV() {
System.out.println("LED TV");
}
};
}
return null;
}
public static void main(String[] args) {
TVSimpleFactory.getTV(TVMODE.LED).createTV();
}
}
Justification
With the Simple Factory, we try to abstract the creation details of the product from our caller. The only thing our caller knows, by calling a Static method and passing the desired parameter it, is that it returns an object of the TV type. But how TV is created, the client code does not know. Actually, they do not care how you create that product. I only care about viewing Sony LED TVs, not how Sony manufactures them.
So whenever you see there are chances to create many implementations of a product go for the Simple factory. But please don’t take this as a Silver bullet. Try to understand the business justification then apply the pattern on it may be it is provocative to use Simple factory for a Business requirements but it may happen you view the problem in a small scope but at a broader scope your decision hurt the design, read the next to see how a simple change in business requirements can hurt the design.
Factory Method
Use the Factory method if the business requirements are more than just product creation. To be precise, if you want to control product creation steps and want to control every step, and steps are customized, then we use the Factory method. To put it a simple way, if you want to control an algorithm/strategy of a family of products, you can think about the Factory method pattern. It plays very well with the GOF Template pattern, where a Template method controls the strategy/algorithm and its steps to create the child are abstracted.
Use the Factory method when you want to make a Framework where you want to take a control from the creation of the Object to the management of that Object. That's unlike the Simple factory, where you only care about the creation of a product, not how to create and manage it.
Recall the Headfirst Pizza example, where the orderPizza() method, creates Pizza, then bakes, cuts, and boxes it. So it is nothing but an algorithm that remains constant across all Pizzas and notes that orderPizza is a template Method.
But you can also add an abstract method called applyTax() in orderPizza(), in the actual implementations (children) of the factory, you actually apply tax computation on a Region basis, so I can tell I have fine control over the Pizza lifecycle — not only the creation, but also the management part.
Back to our example. Now, say our business requirements want us to not only to create the TV, but also take orders and ship the TV based on whether a city shipping charge is applicable.
So, we need to create an algorithm that will create different TVs and ship them. It calculates a shipping charge. The Factory method pattern is ideal here, but we can't achieve it via Simple Factory, so a change is needed in our design
Coding
We create an Interface for TV called ITV. LED TV and black&White TV implement this interface. After that, we create an abstract class called AbstractFactory where we maintain the algorithm/strategy in a template method and abstract the necessary part of the strategy. So, in the subclass of the factory, we can implement them according to business requirement.
Coding Template
Interface of Product
/**
*
*/
package com.example.factory;
/**
* @author Shamik Mitra
*
*/
public interface ITV {
public void createTV();
}
-------------------------
AbstractFactory Class
------------------------
/**
*
*/
package com.example.factory;
import com.example.factory.TVSimpleFactory.TVMODE;
/**
* @author Shamik Mitra
*
*/
public abstract class AbstractFactory {
public final void orderTV() {
createTV();
int charge= shippingCharge();
System.out.println("Shipping charge :: " + charge + " INR");
}
protected abstract int shippingCharge();
protected abstract void createTV();
}
-----------------------
Concrete Factory
----------------------
/**
*
*/
package com.example.factory;
/**
* @author Shamik Mitra
*
*/
public class LEDTVFactory extends AbstractFactory {
@Override
public int shippingCharge() {
// TODO Auto-generated method stub
return 1000;
}
@Override
public void createTV() {
new ITV() {
@Override
public void createTV() {
System.out.println("LED TV");
}
}.createTV();
}
public static void main(String[] args) {
AbstractFactory factory = new LEDTVFactory();
factory.orderTV();
}
}
Justification
With the Factory method, we not only abstract product creation, but take one step further. Here, we also abstract the factory that produces the TV. So the benefits are that we can control the creation and management of the product (i.e TV). If you examine the above code, you can see we abstract the TV with the ITV interface, and in the Abstract factory, we create a template method that controls the TV lifecycle — create TV and shipping cost calculations — and make them abstract so children of the abstract factory can change them accordingly.
We can say the Factory method abstracts the creator from the caller. It is one level more abstract than Simple factory.
Benefits
Create a framework.
Control product lifecycle.
Opinions expressed by DZone contributors are their own.
Comments