Factory Design Pattern

In this post, we will learn how to implement the Factory design pattern in Java with step by step example.
Factory design pattern define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Real-world Example

Consider an example of using multiple database servers like SQL Server, Oracle, MySQL etc. If you are developing an application that uses the SQL Server database and in the future, if you want to change the database from SQL Server to Oracle then you will need to modify all your code related SQL server connection. So you can use the Factory design pattern for loose-coupling by eliminating the need to bind application-specific classes into the code.

Factory Design Pattern Implementation

Let's create a simple Pizza Store application to demonstrate the implementation of the Factory pattern in Java.
Let's write the source code step by step as per the above class diagram.

Step 1: Create an abstract class called Pizza which abstract pizza-related data:

import java.util.ArrayList;

abstract public class Pizza {
    String name;
    String dough;
    String sauce;
    ArrayList toppings = new ArrayList();

    public String getName() {
        return name;
    }

    public void prepare() {
        System.out.println("Preparing " + name);
    }

    public void bake() {
        System.out.println("Baking " + name);
    }

    public void cut() {
        System.out.println("Cutting " + name);
    }

    public void box() {
        System.out.println("Boxing " + name);
    }

    public String toString() {
        // code to display pizza name and ingredients
        StringBuffer display = new StringBuffer();
        display.append("---- " + name + " ----\n");
        display.append(dough + "\n");
        display.append(sauce + "\n");
        for (int i = 0; i < toppings.size(); i++) {
            display.append((String) toppings.get(i) + "\n");
        }
        return display.toString();
    }
}

Step 2: Create Concrete Pizza classes which extends abstract Pizza class - CheesePizza, ClamPizza, VeggiePizza, and PepperoniPizza class:

public class CheesePizza extends Pizza {
    public CheesePizza() {
        name = "Cheese Pizza";
        dough = "Regular Crust";
        sauce = "Marinara Pizza Sauce";
        toppings.add("Fresh Mozzarella");
        toppings.add("Parmesan");
    }
}

public class ClamPizza extends Pizza {
    public ClamPizza() {
        name = "Clam Pizza";
        dough = "Thin crust";
        sauce = "White garlic sauce";
        toppings.add("Clams");
        toppings.add("Grated parmesan cheese");
    }
}

public class VeggiePizza extends Pizza {
    public VeggiePizza() {
        name = "Veggie Pizza";
        dough = "Crust";
        sauce = "Marinara sauce";
        toppings.add("Shredded mozzarella");
        toppings.add("Grated parmesan");
        toppings.add("Diced onion");
        toppings.add("Sliced mushrooms");
        toppings.add("Sliced red pepper");
        toppings.add("Sliced black olives");
    }
}

public class PepperoniPizza extends Pizza {
    public PepperoniPizza() {
        name = "Pepperoni Pizza";
        dough = "Crust";
        sauce = "Marinara sauce";
        toppings.add("Sliced Pepperoni");
        toppings.add("Sliced Onion");
        toppings.add("Grated parmesan cheese");
    }
}

Step 3: Create a SimplePizzaFactory class which produces pizza object based on the type of the pizza - SimplePizzaFactory java class.

public class SimplePizzaFactory {

    public Pizza createPizza(String type) {
        Pizza pizza = null;

        if (type.equals("cheese")) {
            pizza = new CheesePizza();
        } else if (type.equals("pepperoni")) {
            pizza = new PepperoniPizza();
        } else if (type.equals("clam")) {
            pizza = new ClamPizza();
        } else if (type.equals("veggie")) {
            pizza = new VeggiePizza();
        }
        return pizza;
    }
}

Step 4: Let's create PizzaStore to order the Pizza:

package com.ramesh.gof.factory.pizzas;

public class PizzaStore {
    SimplePizzaFactory factory;

    public PizzaStore(SimplePizzaFactory factory) {
        this.factory = factory;
    }

    public Pizza orderPizza(String type) {
        Pizza pizza;

        pizza = factory.createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    }
}

Step 5: Let's test the Factory Pattern with below PizzaTestDrive:

public class PizzaTestDrive {

    public static void main(String[] args) {
        SimplePizzaFactory factory = new SimplePizzaFactory();
        PizzaStore store = new PizzaStore(factory);

        Pizza pizza = store.orderPizza("cheese");
        System.out.println("We ordered a " + pizza.getName() + "\n");

        pizza = store.orderPizza("veggie");
        System.out.println("We ordered a " + pizza.getName() + "\n");
    }
}

Output :

Preparing Cheese Pizza
Baking Cheese Pizza
Cutting Cheese Pizza
Boxing Cheese Pizza
We ordered a Cheese Pizza

Preparing Veggie Pizza
Baking Veggie Pizza
Cutting Veggie Pizza
Boxing Veggie Pizza
We ordered a Veggie Pizza
View source code Factory Design Pattern on my GitHub repository: https://github.com/RameshMF/gof-java-design-patterns

Advantage of Factory Design Pattern

  • Factory Method Pattern allows the sub-classes to choose the type of objects to create.
  • It promotes the loose-coupling by eliminating the need to bind application-specific classes into the code. That means the code interacts solely with the resultant interface or abstract class so that it will work with any classes that implement that interface or that extends that abstract class.

Applicability

Use the Factory Method pattern when

  • a class can't anticipate the class of objects it must create
  • a class wants its subclasses to specify the objects it creates
  • classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate


Comments

  1. I enjoyed reading your post. I will share it with my other friends as the information is really very useful. Keep sharing your excellent work. if you want to become a java developer, then join Best java classes in jaipur

    ReplyDelete
  2. The information that you have shared is really useful for everyone. If someone wants to know about EHS Software and Occupational Safety Softwares I think this is the right place for you.

    ReplyDelete
  3. Am I the only person, who can not understand the structure? I can not connect it with a code and it doesn't work at all. Did anybody have the same problem?

    ReplyDelete
  4. A convenient pattern if your class doesn`t anticipate the patterns it must create, but what pattern should we use if all is vice versa. Will be interesting to read about it to.

    ReplyDelete
  5. you are missing to diaplay PizzaStore class in previous article as well

    ReplyDelete

Post a comment