Factory Method Design Pattern

Factory Method Design Pattern

What is the Factory Method Pattern?

In Java applications, you might be often using the new operator to create an object of a class. This is often fine for small Java programs. But when you work on large scale enterprise class applications, the amount of code to create objects will gradually increase and will become scattered across the application. If class names are hard coded in such code, the complexities of managing the code will keep increasing as you add new classes to the application. To address such concerns, you can use the factory method pattern. This pattern is a classic Gang of Four creational design pattern that is concerned with the creation of objects in an application. As the name suggests, the factory method pattern makes use of classes that acts as factories to create objects. This pattern favors method invocation instead of making direct constructor calls to create objects.

In the factory method pattern, you provide an interface, which can be a Java interface or an abstract class to create objects. A factory method in the interface defers the object creation to one or more concrete subclasses at run time. The subclasses implement the factory method to select the class whose objects need to be created.

Participants in the Factory Method Pattern

To understand how the factory method pattern works, consider a pizza store. In an application, you can model the pizzas as concrete Pizza objects, such as CheesePizza, PepperoniPizza, and VeggiePizza. Just as in any pizza store, a customer can only order a pizza and not make it. In the application, you can create an abstract class, say BasePizzaFactory with a factory method to create a pizza. You can then create a subclass of BasePizzaFactory, called PizzaFactory to implement the factory method. In the factory method, you can create and return a proper Pizza object. The object returned will be the proper subtype, and configured for use in your code.

The components of the factory method pattern in the context of the pizza store can be summarized as:

  • Product (Pizza): Is an interface or an abstract class whose subclasses are instantiated by the factory method.
  • ConcreteProduct (CheesePizza, PepperoniPizza, and VeggiePizza): Are the concrete subclasses that implement/extend Product. The factory method instantiates these subclasses.
  • Creator (BasePizzaFactory): Is an interface or an abstract class that declares the factory method, which returns an object of type Product.
  • ConcreteCreator (PizzaFactory): Is a concrete class that implements the factory method to create and return a ConcreteProduct to Client.
  • Client: Asks the Creator for a Product.

A Client that requires a ConcreteProduct does not create any object but instead asks the Creator for it. The ConcreteCreator implements the factory method to create the object transparently from the Client. As a result, the Client is not required to be aware of any ConcreteProduct and how they are created. This approach advocates the Object Oriented Programming principle “Program to an interface, not an implementation“, which leads to polymorphism, a key feature of object-oriented programming. In addition, as object creation is centralized in the ConcreteCreator, any changes made to a Product or any ConcreteProduct does not affect the Client.

Applying the Factory Method Pattern

To apply the factory method pattern in the pizza store application, let us first create the abstract Pizza class and its subclasses.

   //package guru.springframework.gof.factoryMethod;

public abstract class Pizza {
    public abstract void addIngredients();

    public void bakePizza() {
        System.out.println("Pizza baked at 400 for 20 minutes.");
    }
}

 

   //package guru.springframework.gof.factoryMethod;

public class CheesePizza extends Pizza {

    @Override
    public void addIngredients() {
        System.out.println("Preparing ingredients for cheese pizza.");
    }
}

 

   //package guru.springframework.gof.factoryMethod;

public class PepperoniPizza extends Pizza {
    @Override
    public void addIngredients() {
        System.out.println("Preparing ingredients for pepperoni pizza.");
    }
}

 

   //package guru.springframework.gof.factoryMethod;

public class VeggiePizza extends Pizza {
    @Override
    public void addIngredients() {
        System.out.println("Preparing ingredients for veggie pizza.");
    }
}

In the examples above, we wrote the Pizza class with an abstract addIngredients() method and defined a bakePizza() method. We then wrote three subclasses: CheesePizza, PepperoniPizza, and VeggiePizza that provide their own implementation of the addIngredients() method. The subclasses being derived from Pizza inherit the bakePizza() method defined in Pizza.

Next, we will create the abstract BasePizzaFactory class, which is the Creator in the application.

   //package guru.springframework.gof.factoryMethod;

public abstract class BasePizzaFactory {
    
    public abstract Pizza createPizza(String type);
}

In the example above, we wrote the BasePizzaFactory class with a createPizza() factory method. Notice that we have declared the createPizza() method as abstract. We will provide the factory method implementation in a concrete subclass, PizzaFactory, which will be the ConcreteCreator of the application.

   //package guru.springframework.gof.factoryMethod;

public class PizzaFactory extends BasePizzaFactory{
    @Override
    public  Pizza createPizza(String type){
        Pizza pizza;
        switch (type.toLowerCase())
        {
            case "cheese":
                pizza = new CheesePizza();
                break;
            case "pepperoni":
                pizza = new PepperoniPizza();
                break;
            case "veggie":
                pizza = new VeggiePizza();
                break;
            default: throw new IllegalArgumentException("No such pizza.");
        }

        pizza.addIngredients();
        pizza.bakePizza();
        return pizza;
    }
}

In the example above, we wrote the PizzaFactory class and implemented the createPizza() factory method in it. In the createPizza() method, we used a switch statement to create a Pizza object based on the parameter passed to the method. We then made calls to the addIngredients() and bakePizza() methods on the Pizza object before returning it to the caller.

Now, let us write a unit test for our example class to observe the factory method pattern at work. In our test, we make two calls to the factory method with different String parameters. The parameter tells our factory what kind of pizza we want.

   //package guru.springframework.gof.factoryMethod;

import org.junit.Test;

public class PizzaFactoryTest {
    @Test
    public void testMakePizzas(){
        BasePizzaFactory pizzaFactory = new PizzaFactory();
        Pizza cheesePizza = pizzaFactory.createPizza("cheese");
        Pizza veggiePizza = pizzaFactory.createPizza("veggie");
    }
}

As you can see in the above example, we have not created any concrete Pizza objects in the code. Therefore, if we enhance the Pizza implementation classes in a newer release, we do not require updating any client or test code. We can safely rely on the Creator to provide us the enhanced object. When you run the code above, you will see this output:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running guru.springframework.gof.factoryMethod.PizzaFactoryTest
Preparing ingredients for cheese pizza.
Pizza baked at 400 for 20 minutes.
Preparing ingredients for veggie pizza.
Pizza baked at 400 for 20 minutes.
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.346 sec - in g
uru.springframework.gof.factoryMethod.PizzaFactoryTest

Conclusion

Java APIs and frameworks extensively use the factory method pattern. You should also consider using it because of the advantages it provides. The key advantage, that you have already learned, is how the factory method pattern helps encapsulate object creation code from client code. This decouples your client code from the concrete classes you need to instantiate. Therefore, while developing applications, if you see an opportunity to encapsulate object creation code, apply the factory method pattern. Also, by using this pattern you will have a centralized location for object creation code, which will make it easy for you to debug and troubleshoot.

Source Code

The source code for this post is available on github. You can download it here.

18 comments on “Factory Method Design Pattern

  1. October 27, 2015 at 5:18 am

    Hi, I want to make a Factory on Spring Boot (Example: I have Resource, but as an attribute I create other child objects), Can I use this?, I use this on computer enginyeering, but I don’t know if it can be done otherwise on Spring Boot.

    Thanks.

    Reply
    • October 27, 2015 at 8:20 am

      Yes you can do this. Spring Boot automates a lot, but it does not prevent you from using traditional Spring configuration.

      Reply
  2. October 27, 2016 at 6:30 pm

    Hi,
    It looks like PizzaFactory#createPizza implements the Simple Factory Design Pattern, it is not a Factory Method implementation.
    Please have a look at http://corey.quickshiftconsulting.com/blog/first-post and various discussions on StackOverflow.
    P.S.
    I’m trying to make things clear for myself in the first place, so I’m open for the discussion.

    Reply
    • May 30, 2020 at 5:00 am

      I don’t see why this is not the FactoryMethod pattern. In this example the ConcreteCreator “PizzaFactory” implements the Creator interface “BasePizzaFactory” to create various implementations of “Pizza”. If you look into the GoF book in chapter 3.3 http://www.uml.org.cn/c++/pdf/DesignPatterns.pdf you find the exact same pattern structure. The SimpleFactory in contrast doesn’t have a Creator interface like “BasePizzaFactory”. So this is a correct example

      Reply
  3. January 17, 2018 at 3:54 pm

    I agree; this article demonstrates the Simple Factory design pattern, not the Factory Method pattern.

    Reply
    • September 3, 2022 at 3:11 pm

      This article does demonstrate Factory Method Design Pattern. I think the confusion arises because we’re thinking of the word “method” as simply a function in a class. But I think they use the word “method” as in “procedure to design this thing” or “strategy to design”.
      “The Simple Factory isn’t actually a Design Pattern; it’s more of a programming idiom”, – quote from “Head First Design Patterns”

      But after just reading through that booking I would say only difference between what they described as Simple Factory and Factory Method Pattern is that Simple Factory omits the BasePizzaFactory and you simply have a PizzaFactory without the abstract class, basically not allowing for more than one factory to exist without major code changes.

      Reply
  4. January 31, 2018 at 2:31 pm

    Hi John:
    Question: If want to put this on a spring boot webapp, what is the best way to persist the created object? would it be injecting the factory into the service and then the factory calls each child’s repository?

    Reply
  5. January 20, 2019 at 8:29 am

    It’s a simple factory class pattern, please don’t use the title as “factory method pattern”.

    Reply
  6. March 25, 2019 at 4:12 am

    Why did you use “BasePizzaFactory”? Can’t we work without “BasePizzaFactory” ? I think this step was unnecessary.

    Reply
    • May 10, 2019 at 7:22 pm

      I wondered exactly the same thing. Adds confusion by raising the question “wait, why?”

      Reply
    • September 3, 2022 at 2:33 pm

      Because sometimes you may want to have multiple factories, for example NYPizzaFactory and ChicagoPizzaFactory. If NY and Chicago use different ingredients for say a Veggie pizza, you can do pizzaFactory.createPizza(“veggie”); and get a different Pizza depending on which factory was used.

      Reply
    • September 18, 2022 at 11:59 pm

      No that extra class is using for achieving dependency inversion principle.

      Reply
  7. December 3, 2019 at 1:48 am

    BasePizzaFactory is merely a abstraction of the factory , YES it could be done without BasePizzaFactory, but in case if you need to change the implementation of the factory , you just need to create a new Factory implementation. This type of practice adheres with SOLID principles.

    Reply
  8. April 1, 2020 at 3:28 pm

    How would you implement the PizzaFactory using generics? I am trying to do so and I am getting checking errors

    Reply
  9. December 18, 2021 at 8:46 pm

    Doesn’t this violate the Open-Closed principle?

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.