Sunday, October 26, 2025

Factory Pattern in Java | Static Factory method Example

Factory design pattern in Java, also known as Factory pattern or static factory method pattern provides and indirect and alternate way of creating object than directly using public constructors in Java. Though constructor is most common way of creating object, it's not always best way to do that. Factory pattern, first introduced by GOF in there timeless classic GOF book as creational pattern offers lot of advantage over public constructor for creating objects. It not only encapsulate logic of object instantiation, but also enforce use of tried and tested design principles like programming for interface than implementation by returning super type of objects. 

This opens doors for further optimization and returning better performance implementation of certain class. Use of Factory method also reduce coupling between different classes, by not using new() operator and subsequently depending on a particular constructor. 

With the growing use of Immutable value object, static factory method also provides an opportunity to cache and reuse, which is critical to reduce memory consumption in your application. 

Apart from mentioned advantages in this article, this pattern has several advantage, best highlighted by Joshua Bloch in it's timeless book, Effective Java

In this Java design pattern tutorial, we will see a simple implementation of Factory design pattern and subsequently learn some best practices around this pattern.

Factory design pattern in Java | Static Factory method Example, Best Practices




Advantages of Factory pattern in Java

Factory design pattern offers several advantage over new() operator for creating object. It not only gives your more flexibility and control on creating different types of object, but also offers you chances to improve performance by caching frequently used Immutable value objects. 

In short following are major benefits of using static factory method pattern in Java.

1) Using static factory method to create object provides encapsulation, which reduces coupling between different classes in your project. When you use new() operator to create object, you are directly coupled with the class, whose object you are creating. 

There is no way to substitute or replace that object, without modifying the class, which uses them. This significantly limit your capability to provide a higher performance version of that class. Your client class is also tightly coupled with that class since you are effectively calling a constructor of that class using new() operator. 

If down the road, that class changes it's constructor, it will break all client code. By using Factory method pattern, you not only encapsulate object instantiation process, but also enforce best practices, in terms of programming for interfaces than implementation. 

Since static factory method return interface rather than implementation, client code will not be affected, if factory returns a better implementation in future. 

One of the best example of this pattern I have experience in, while using EnumSet in Java. EnumSet has no public constructor, only way to create an instance of EnumSet is by using one of the several static factory methods provided e.g. EnumSet.noneOf() creates an empty EnumSet, while EnumSet.of() is used to create Set of Enum constants. Factory method decides whether to return a RegularEnumSet or JumboEnumSet, depending upon size of Enum. 

If number of Enum constants in a particular Enum type is less than 64, then it returns a RegularEnumSet, which is backed by a long variable, while if size of Enum is more than 64, then it returns JumboEnumSet, which is backed by long array. 

Another worth noting thing in that example is that, they not just recommend but enforce to use Factory methods to create EnumSet by making implementation classes RegularEnumSet and JumboEnumSet, along with there constructor as package-private.

2) Extension to previous points, Factory makes it easy to manage related set of objects. It's easy to introduce new type of product, or maintain existing products. Factory method will take care of that, shielding all client code from internals of creating objects.

3) Another advantage of using static factory method pattern for creating objects, particularly value object is improved performance. Since value objects are mostly Immutable and they should be, You might end up with lot of value objects in your system. 

By caching frequently used value objects, you not only reduce memory footprint but also improves performance. Best example of this pattern is valueOf() method of Integer object, which caches Integer object in range of -128 to 127. 

By the way this can result in some surprises if you are comparing Integers using == operator in autoboxing world of post Java 5.

4) One, rather unknown, syntactical advantage of Factory design pattern over new() operator for creating object is type inference. Since new() operator can not infer types, and that's why you always need to specify generic types on both left and right side of an object instantiation expression. 

On the other hand static method can infer types as shown below :

public class ArrayListUtils{
     public static  ArrayList newInstance(){
        return new ArrayList();
    }
}

// Creating objects of ArrayList using static factory method
List strList = new ArrayList(); // no type inference   
List sList = ArrayListUtils.newInstance(); // type inference

You can see that, in second example, we have not specified generic type e.g. <String>, it's inferred by compiler. This may save some bit of typing for you, but you can also use diamond operator <>, introduced in Java 7 for type inference, while creating parametric objects in Java. 

Last, but not least, Factory pattern also reduces coupling, because now your client code is not dependent on several classes, instead they are only dependent on Factory. 

By the way Joshua Bloch has mentioned several advantages and disadvantages of using static factory method in it's all time classic Java title Effective Java. If you haven't read they already, go and must read it.

When to use Factory pattern in Java?

As we have seen Factory design pattern offers lot of advantages for creating objects and should be used to create related set of classes. I don't recommend to provide factory for every single class, because this way you are just adding more classes to your project. 

By the way, It's not mandatory to create your factory as separate class, you can have your static factory method inside the same class e.g. Integer.valueOf(), EnumSet.of() and several others. 

Making Factory a separate class only make sense, when you are creating different types of object, as we are doing in this example. In short, I use Factory design pattern in following scenarios :

1) As Conversion utility, when you need to convert one type into another e.g. Integer.value() can create Integer instance from String, long, double, byte and other data types.

2) An extension to previous point, consider using static factory method for creating value objects, even if you are not caching them right now. You never know, when need comes and you might start caching your Immutable objects.

3) Use Factory design pattern for creating different products, just like in this example. This not only provides better control over supported products but also provides flexibility to add new products and enforce best practices e.g. programming for interfaces .

4) Consider using Factory pattern, if you want to protect your implementation class from client. Example of this is RegularEnumSet and JumboEnumSet, since this classes may change in future, it's wise not to expose them to client. By providing factory methods in EnumSet, we can still use these classes without exposing them to client.

Factory Pattern | Static Factory method Example

This is a simple, straight forward example of Factory design pattern in Java. We are implementing a Supermarket kind of application, where user can shop different items and finally we need to calculate total cost of Items for billing. We have opted for an abstract class Item, instead of interface with abstract method cost(). 

As a Java developer, I know choosing between abstract class and interface is a tricky question, but here I preferred abstract class, because Item may evolve and might have some concrete behaviour apart from abstract cost() method. 


I have also made return type of cost as BigDecimal, instead of using float or double as it's a Java best practice, not to use floating point types for monetary calculation. If you are not aware of the issues of using float and double for financial calculate, I suggest reading this article or consider buying Java Puzzlers book. 

Now, in order to create different Items, we have three concrete implementation Soap, Snacks and Toy, we have created a Factory class called ItemFactory. 

ItemFactory accepts type of Item and return an object of that type, two thing which is worth noting is return type of Factory method, which is Item (super type) and not Soap, Snacks or Toy; and use of Enum for representing item type rather than String. Always Prefer Enum over String for representing fixed set of things. 


Finally we have a class called FactoryPatterTest, which make use of this system and create some items and calculates total amount. One thing to note while using BigDecimal is to storing reference back. 

If you look at code you will find that we have initialized total as BigDecimal.ZERO and then subsequently adding cost of items into that. It's quite common not to store reference back to total variable, which will then print zero at the end of calculation. 

Since BigDecimal is Immutable object, add() method returns a separate BigDecimal object, if we don't store them back, we lose result of calculation. This is true with any Immutable object including String, Integer and Long and developer should  careful about that.

Item.java
-----------
import java.math.BigDecimal;

public abstract class Item {
    protected ItemType type;
   
    public Item(ItemType type){
        this.type = type;
    }
   
    public abstract BigDecimal cost();

    @Override
    public String toString() {
        return type.name();
    }
   
   
}

ItemType.java
---------------
public enum ItemType {
    SOAP, SNACKS, TOY;
}

Soap.java
----------
import java.math.BigDecimal;

public class Soap extends Item{

    Soap(ItemType type){
        super(type);
    }
   
    @Override
    public BigDecimal cost() {
       return BigDecimal.valueOf(2);
    }
   
}


Snacks.java
------------
import java.math.BigDecimal;

public class Snacks extends Item {

    Snacks(ItemType type){
        super(type);
    }
   
    @Override
    public BigDecimal cost() {
        return BigDecimal.valueOf(3);
    }
   
}


Toy.java
---------
import java.math.BigDecimal;

public class Toy extends Item{

    Toy(ItemType type){
        super(type);
    }
   
    @Override
    public BigDecimal cost() {
        return BigDecimal.valueOf(2.5);
    }
   
}


ItemFactory.java
-----------------
/**
 *  Implementation of Factory design pattern to create objects in Java.
 *
 * @author Javin
 */
public class ItemFactory {
   
    public static Item createItem(ItemType type){
        Item item = null;
        switch(type){
            case SOAP:
                item = new Soap(type);
                break;
            case SNACKS:
                item = new Snacks(type);
                break;
            case TOY:
                item = new Toy(type);
                break;
            default:
                throw new IllegalArgumentException("Invalid type");
        }
       
        return item;
    }
}

FactoryPatternTest.java
------------------------


import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/*
 * Test class to show how to use Factory design pattern to create objects in Java.
 * Creates different items from ItemFactory in this example.
 *
 * @author Javin Paul
 */
public class FactoryPatternTest {
                   
    public static void main(String args[]){
   
        List shoppingCart = new ArrayList();
       
        shoppingCart.add(ItemFactory.createItem(ItemType.SOAP));
        shoppingCart.add(ItemFactory.createItem(ItemType.SNACKS));
        shoppingCart.add(ItemFactory.createItem(ItemType.TOY));
       
        BigDecimal total = BigDecimal.ZERO;
        for(Item item : shoppingCart){
            total = total.add(item.cost()); // remember to store BigDecimal 
//reference back in total
        }
       
        System.out.println("Total cost of Items : " + shoppingCart +": $" 
+ total);
    } 
   
}

Output:
Total cost of Items : [SOAP, SNACKS, TOY]: $7.5




Summary

1) Make sure your Factory method is static, if your Factory is not Singleton. It's debatable to make a Factory class static or Singleton, as both provide similar value, I personally prefer to keep it simple by making it static. If you are more interested in understanding pros and cons of choosing Singleton or Static class, I suggest reading that link.

2) Make sure to return super type either an abstract class or interface from Factory method. For example, in this sample program, our factory produces Item and that's why return type of createItem() factory method is interface. 

This is one of the best practice to follow, while coding in object-oriented programming language. It's also known as programming for interface than implementation and it result in more flexible code. As you can see by returning interface type, we can easily add few more Items without affecting other modules of project.

3) While using Factory design pattern to create related objects i.e. objects of same super type, prefer Enum over String to pass type of actual object. Using Enum over String has several benefits, including compile time type safety, better error handling and complete control over types of objects created by Factory. 

In our sample program, createItem(ItemType type) accepts an enum, rather than a String to specify requested type of object. To know more about Enum in Java, see this article.

That's all about Factory pattern in Java. There are different ways to implement Factory pattern, but using it to create related objects, i.e. objects which are part of same type hierarchy is one of common ways to use it. 

There are lot of examples of Factory pattern is available across different open source Java project and in JDK e.g. valueOf() method, which is used to convert one type into another is an example of Factory pattern.

Further Reading
I strongly suggest to read first Item of Effective Java Book to understand merits of using public constructor and static factory method for creating objects in Java. Joshua Bloch has shared lot of wisdom from his extensive experience in that write-up, and it's must read for any Java developer, who is either new or familiar with factory design pattern. 

Another books, which I recommend to understand factory pattern is my all time favorite Head First design pattern, which has it's unique way of comparing pros and cons of using factory pattern or any Java design pattern.

Related Java design Pattern tutorials 

No comments :

Post a Comment