What is the Factory Method Pattern?
If you are looking for a way to encapsulate the creation of objects, factory patterns are just what you need. There are multiple factory patterns but in this post I will just be focusing on the Factory Method Pattern. It is a factory pattern so we should expect the creation of objects to be encapsulated but what is the method part of it? Specifically, it allows subclasses to determine the creation of objects through the implementation of an abstract parent method. So, if I was to make a generic class diagram, it would looks something like this.
So our Creator class has an abstract method called factoryMethod() that it’s subclasses must implement. In this diagram, the ConcreteCreator is the only subclass. It determines which Product objects to create. In this diagram, it is the ConcreteProduct. So the creation of the ConcreteProduct is encapsulated in ConcreteCreator. The clients of Creator will only get references to the Product interface, thus supporting the good design practice of depending on abstractions instead of concrete objects.
The Factory Method Pattern in Use
Let’s see what the Factory Method Pattern looks like when we put it to use. I am going to use two well known fast food restaurants in our example, McDonald’s and Burger King as our concrete creators. Each restaurant provides a burger selection as part of a meal (it’s product). Each restaurant has their own specific way of creating a burger (concrete product).
So let’s make two concrete creator classes McDonalds and BurgerKing that implement the abstract creator class BurgerJoint. It has an abstract method CreateBurger() that our concrete creators will implement. This will be our factory method. We’ll call the abstract product class Burger and we will create four concrete classes (McDonaldsBurger, McDonaldsCheeseBurger, BurgerKingBurger, BurgerKingCheeseBurger) that the concrete creators will be able to create. See the class diagram below showing our classes and their relationships.
Our Burger will have a name, type of bun and any number of condiments which the subclasses will be responsible for assigning values to. Operations would include Grill(), Prepare() and Wrap(). BurgerJoint has an operation to OrderBurger() which will make use of the Burger operations to complete its function.
Let’s first take a look at the implementation of Burger.
Burger.cpp
You can see there is no specialization of the Grill() method. But Prepare() and Wrap() do print out the name of the Burger where Prepare() additionally prints out the bun type used and the condiments of the Burger. These attributes are determined by the subclasses of Burger. What do those subclasses look like? Let’s have a look, shall we?
McDonaldsBurger.cpp
So you can see the class basically configures the parent class’s protected attributes. The same can be said for the other subclasses of Burger as you can see below.
McDonaldsCheeseBurger.cpp
BurgerKingBurger.cpp
BurgerKingCheeseBurger.cpp
So now that we are familiar with the subclasses of Burger, we can look at how the subclasses of BurgerJoint decide which Burger subclass to create via the Factory Method Pattern. Let’s start with the BurgerJoint implementation.
BurgerJoint.cpp
We see in the OrderBurger() operation that the CreateBurger() operation is called. This method is abstract so the subclasses of BurgerJoint would decide how to make the specified burger based on the type of burger specified in a parameter from the OrderBurger() operation. The returned type is a Burger, so BurgerJoint only depends on the parent Burger class and not its derived classes. This supports the “depend on abstractions, not concrete classes” design principle. Let’s take a look at our BurgerJoint subclasses to see how our Factory Method CreateBurger() is implemented.
McDonalds.cpp
BurgerKing.cpp
As you can see, the implementation is pretty straight forward for both. If the type specified is “cheeseburger”, each BurgerJoint creates their style of cheeseburger, otherwise the default burger is created.
Now let’s put everything together and implement a program exercising our Factory Method Pattern BurgerJoint implementation.
BurgerJointTest.cpp
First, a BurgerJoint is created. The first one created is McDonalds. We order each of the Burgers McDonalds provides and then do the same for BurgerKing. When we run the program it looks like this…
Grill for 5 minutes... done
Preparing McDonald's Cheese Burger
Add bottom half of Plain Bun...
Add grilled burger patty...
Adding condiments :
Ketchup
Mustard
Onions
Pickle
Cheese
Adding top Plain Bun
Wrapping your McDonald's Cheese Burger
I just ordered a McDonald's Cheese Burger
Grill for 5 minutes… done
Preparing McDonald’s Burger
Add bottom half of Plain Bun…
Add grilled burger patty…
Adding condiments :
Ketchup
Mustard
Onions
Pickle
Adding top Plain Bun
Wrapping your McDonald’s Burger
I just ordered a McDonald’s Burger
Grill for 5 minutes… done
Preparing Burger King Cheese Burger
Add bottom half of Sesame Seed Bun…
Add grilled burger patty…
Adding condiments :
Ketchup
Mustard
Pickle
Cheese
Adding top Sesame Seed Bun
Wrapping your Burger King Cheese Burger
I just ordered a Burger King Cheese Burger
Grill for 5 minutes… done
Preparing Burger King Burger
Add bottom half of Sesame Seed Bun…
Add grilled burger patty…
Adding condiments :
Ketchup
Mustard
Pickle
Adding top Sesame Seed Bun
Wrapping your Burger King Burger
I just ordered a Burger King Burger
The output shows that we go through the steps of ordering each Burger available at each of the BurgerJoints.
So there you have it. The Factory Method Pattern in action. I hope you enjoyed this post. You can find all the code here. Have you used the Factory Method pattern recently? If so, please share your thoughts in the comments section below.
Recommended Resources
Here are some resources I recommend for more information on the Factory Method Pattern
Head First Design Patterns: A Brain-Friendly Guide
Design Patterns: Elements of Reusable Object-Oriented Software