Design Patterns: Factory Method

Seri Oh
Capgemini Microsoft Blog
4 min readJun 27, 2024
Photo by Aleksandr Popov via Unsplash

Welcome to the second instalment in my design patterns series, in which I’ll be sharing what I’ve learned about the Factory Method design pattern. Click here for part one of the series, focusing on the Template Method pattern.

What is the Factory Method?

The Factory Method pattern uses a method to return an instance of one of many possible child classes which all inherit from the same base class. The instance of the child class is determined at runtime.

The Factory method is part of a family called Creational design patterns which handle object creation while trying to be as flexible and reusable as possible.

What are the benefits of the Factory Method design pattern?

The Factory Method design pattern is beneficial to use when the object to create is not known until runtime. We can change it dynamically, if we know the classes that can be chosen from all have the same base class.

Another benefit is that it encapsulates the creation of the object, helping us create more maintainable code since we centralise the code that selects the class to instantiate. This allows us to hide the child classes from users that are irrelevant to them.

Example

Let’s say we have a restaurant with customers who order burgers from via an application.

Here is the burger abstract class inherited by all the subclasses representing each burger variant available on the menu.

public abstract class Burger
{
string name;
real price;

public void SetName(string _name)
{
name = _name;
}

public string GetName()
{
return name;
}

public void SetPrice(real _price)
{
price = _price;
}

public real GetPrice()
{
return price;
}

public void Prepare()
{

}

public void Serve()
{

}
}

The Burger class has name and price fields with get and set methods and methods to prepare and serve the burger — methods and fields which will be inherited by all child burgers. Our restaurant has two types of burgers on the menu which extend the base class, containing a constructor method that sets Name and Price fields and overrides the prepare and serve methods:

public class BeefBurger : Burger
{
public Burger BeefBurger()
{
SetName("Beef burger");
SetPrice(9.50);
}

public void Prepare()
{
"Preparing beef burger"
}

public void Serve()
{
"Your beef burger is ready!"
}
}
public class ChickenBurger : Burger
{
public Burger ChickenBurger()
{
SetName("Chicken burger");
SetPrice(8.50);
}

public void Prepare()
{
"Preparing chicken burger"
}

public void Serve()
{
"Your chicken burger is ready!"
}
}

We also have the ordering application class that orders the burgers dynamically based on user input:

public class OrderingApplication()
{
public Burger Main(string[] _args)
{
CustomerInput customerInput = //get user input;
Burger burger = new Burger();

if (customerInput == "Chicken")
{
burger = new ChickenBurger();
return burger;
}

else if (customerInput == "Beef")
{
burger = new BeefBurger();
return burger;
}

FulfillOrder();
}

public void FulfillOrder()
{
burger.Prepare();
burger.Serve();
}
}

With the above class, we can dynamically order the burger based on the user input. However, there is a problem: the ordering functionality is tightly coupled with burger creation. In future, if we add more items to the menu, it means we need to make more changes in this code. Loose coupling makes the code easier to maintain and isolates the burger creation code into a separate class so that the menu can be amended without affecting the rest of the application.

Instead, we can create a burger factory class that encapsulates the creation code with a method called makeBurger:

public class BurgerFactory
{
public Burger MakeBurger(string _customerInput)
{
if (customerInput == "Chicken")
{
burger = new ChickenBurger();
return burger;
}

else if (customerInput == "Beef")
{
burger = new BeefBurger();
return burger;
}
}
}

And we can call this from our ordering application:

public class OrderingApplication()
{
public Burger Main(string[] _args)
{
CustomerInput customerInput = //get user input;
BurgerFactory burgerFactory = new BurgerFactory();
Burger burger;

burger = burgerFactory.MakeBurger(customerInput);

if (burger != null)
{
FulfillOrder();
}
}

public void FulfillOrder()
{
burger.Prepare();
burger.Serve();
}
}

The order application class doesn’t need to know the details of what kind of burger is being ordered — giving it the type Burger is enough since all burgers are a subclass of Burger. The type created is still dynamic since the customer input is passed to the MakeBurger method.

Our new BurgerFactory class allows modification to creation code and allows you to add new types of objects (new burgers on the menu) without impacting the ordering application class — if we would like to make modifications in the creation code, we can simply make changes in the BurgerFactory and add the new child class to the hierarchy without changing code in the order application. The factory method also allows easier maintenance and code reuse since all the common methods/characteristics are shared from the base class.

What are the limitations?

Of course, with these benefits must also come some limitations — since you need to add more classes to your code for every child class, it can increase complexity of the code and can make it more difficult to read/follow.

In order to use this pattern, you must also know that all the possible objects that can be created ultimately inherit from the same base class.

I hope this article has helped you learn about the Factory Method design pattern and wish you luck on your coding journey! Stayed tuned for more.

If you want to learn more about the Microsoft Team here at Capgemini, take a look at our open roles and consider joining the team!

--

--