Factory Method Pattern

Anubhav Gupta
4 min readOct 26, 2024

The Factory Method Pattern is a creational design pattern that defines an interface for creating an object, but lets subclasses decide which class to instantiate. This pattern delegates the instantiation logic to subclasses, allowing them to create different types of products.

Key Principles of the Factory Method Pattern

  1. Delegation of Object Creation: The Factory Method Pattern shifts the responsibility of object creation from a base class to its subclasses, following the principle of “programming to an interface, not an implementation.”
  2. Single Responsibility Principle: Each subclass (factory) is responsible for creating specific types of objects. This keeps the code modular and manageable.
  3. Flexibility and Extensibility: Since subclasses decide which object to create, adding new types is simple; you only need to create a new subclass to produce a new type of object without modifying existing code.

Factory Method Pattern in the Burger Example

In the burger example, we use a hierarchy of restaurant types to create different kinds of burgers. Each restaurant represents a specific factory, encapsulating the creation of a particular type of Burger. This approach illustrates the Factory Method Pattern well because each subclass overrides the factory method (createBurger()) to produce a specific burger type.

Structure

  1. Product Interface (Burger): This defines the contract (i.e., prepare method) that all burger types will follow.
  2. Concrete Product Classes (FalafelBurger, QuinoaBurger, TofuBurger): These implement the Burger interface, each defining a unique prepare method to differentiate the type of burger.
  3. Creator (Restaurant Class): This is an abstract class that contains the orderBurger() method, which calls createBurger() to get a Burger instance. This method acts as a template method for preparing a burger, handling the common preparation process.
  4. Concrete Creators (FalaFelRestaurant, QuinoaRestaurant, TofuRestaurant): These subclasses extend Restaurant and implement the createBurger() factory method to instantiate specific types of burgers.

Explanation of Flow

  • Client Code: When the client requests a burger through orderBurger(), it doesn't know or care about the specific type of burger being created.
  • Factory Method (createBurger()): The abstract Restaurant class contains an abstract createBurger() method. Each subclass implements this method to create a specific burger type.
  • Dynamic Behavior: When a FalaFelRestaurant instance is asked to orderBurger(), the createBurger() method creates a FalafelBurger. Similarly, a QuinoaRestaurant creates a QuinoaBurger, and so on.

Advantages of Using Factory Method Pattern in the Burger Example

  1. Code Reusability: The Restaurant class’s orderBurger() method handles the preparation process in one place, making it reusable across different burger types.
  2. Easy Extensibility: Adding a new type of burger only requires adding a new Burger subclass and a new Restaurant subclass that implements createBurger() to return the new burger type.
  3. Encapsulation: The client code does not need to know the specific burger classes or the creation logic, which is hidden within each Restaurant subclass.

Burger Interface

public interface Burger {
void prepare();
}

Concrete Burger Classes

public class FalafelBurger implements Burger {
@Override
public void prepare() {
System.out.println("Preparing Falafel Burger");
}
}

public class QuinoaBurger implements Burger {
@Override
public void prepare() {
System.out.println("Preparing Quinoa Burger");
}
}

public class TofuBurger implements Burger {
@Override
public void prepare() {
System.out.println("Preparing Tofu Burger");
}
}

Restaurant Abstract Class

public abstract class Restaurant {
// Template method
public Burger orderBurger() {
Burger burger = createBurger(); // Factory Method
burger.prepare();
return burger;
}

// Factory Method
public abstract Burger createBurger();
}

Concrete Restaurant Classes

public class FalaFelRestaurant extends Restaurant {
@Override
public Burger createBurger() {
return new FalafelBurger();
}
}

public class QuinoaRestaurant extends Restaurant {
@Override
public Burger createBurger() {
return new QuinoaBurger();
}
}

public class TofuRestaurant extends Restaurant {
@Override
public Burger createBurger() {
return new TofuBurger();
}
}

Main Class (Client Code)

public class Main {
public static void main(String[] args) {
Restaurant falafelRestaurant = new FalaFelRestaurant();
Restaurant quinoaRestaurant = new QuinoaRestaurant();
Restaurant tofuRestaurant = new TofuRestaurant();

falafelRestaurant.orderBurger(); // Output: Preparing Falafel Burger
quinoaRestaurant.orderBurger(); // Output: Preparing Quinoa Burger
tofuRestaurant.orderBurger(); // Output: Preparing Tofu Burger
}
}

When to Use the Factory Method Pattern

The Factory Method Pattern is suitable when:

  • You want to delegate the responsibility of instantiating objects to subclasses.
  • You need to add new types of objects easily, without modifying existing code.
  • You have a scenario where object creation logic might change frequently based on context.

In the burger example, this approach allows you to add more types of burgers (e.g., VeggieBurger, BlackBeanBurger) by simply creating a new Restaurant subclass, without changing the core Restaurant or Burger code. This flexibility, combined with the ability to encapsulate instantiation logic, is what makes the Factory Method Pattern a powerful choice in scenarios like this.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Anubhav Gupta
Anubhav Gupta

Written by Anubhav Gupta

Machine Learning , Computer Vision and Deep Learning Enthusiast

No responses yet

Write a response