The Factory Method pattern is a creational pattern which defines an interface for creating an object, but doesn't specify what objects the individual implementations of that interface will instantiate.
What this means is that when using this pattern, you can define certain methods and properties of object that will be common to all objects created using the Factory Method, but let the individual Factory Methods define what specific objects they will instantiate.
NOTE: This post is part of a series demonstrating software design patterns using C# and .NET. The patterns are taken from the book Design Patterns by the Gang of Four. Check out the other posts in this series.
The Rundown
- Type: Creational
- Useful? 5/5 (Extremely)
- Good For: Creating objects in a related family.
- Example Code: On GitHub
The Participants
- The Product defines the interfaces of objects that the factory method will create.
- The ConcreteProduct objects implement the Product interface.
- The Creator declares the factory method, which returns an object of type Product. The Creator can also define a default implementation of the factory method, though we will not see that in the below example.
- The ConcreteCreator objects overrides the factory method to return an instance of a Concrete Product.
A Delicious Example
To demo how this pattern works, let's talk about sandwiches.
According to Wikipedia, a sandwich...
...is a food item consisting of one or more types of food, such as vegetables, sliced cheese or meat, placed on or between slices of bread, or more generally any dish wherein two or more pieces of bread serve as a container or wrapper for some other food.
So put two pieces of bread around anything edible, and it's a sandwich. Yes, that means hot dogs are sandwiches.
Let's build some classes to demo how we can use Factory Method to create a variety of different sandwiches.
For this tutorial, we'll say that sandwiches are comprised of ingredients. We'll need an abstract class Ingredient
to represent this, and said Ingredient
class is also our Product participant:
/// <summary>
/// Product
/// </summary>
abstract class Ingredient { }
Now let's instantiate a few classes to represent common ingredients in sandwiches (our ConcreteProduct participants):
/// <summary>
/// Concrete Product
/// </summary>
class Bread : Ingredient { }
/// <summary>
/// Concrete Product
/// </summary>
class Turkey : Ingredient { }
/// <summary>
/// Concrete Product
/// </summary>
class Lettuce : Ingredient { }
/// <summary>
/// Concrete Product
/// </summary>
class Mayonnaise : Ingredient { }
What we want to do is build a factory that will allow us to build different kinds of sandwiches using the same set of ingredients. What will differ between the kinds of sandwiches will be the amount and order of said ingredients.
First, let's build an abstract class Sandwich
that represents all possible kinds of sandwiches (this is the Creator participant):
/// <summary>
/// Creator
/// </summary>
abstract class Sandwich
{
private List<Ingredient> _ingredients = new List<Ingredient>();
public Sandwich()
{
CreateIngredients();
}
//Factory method
public abstract void CreateIngredients();
public List<Ingredient> Ingredients
{
get { return _ingredients; }
}
}
Note the CreateIngredients()
method; this method is the Factory Method which gives the pattern its name. It's not implemented here because that implementation is left up to the ConcreteCreator classes that we now need to define. Let's start off with a basic turkey sandwich:
/// <summary>
/// Concrete Creator
/// </summary>
class TurkeySandwich : Sandwich
{
public override void CreateIngredients()
{
Ingredients.Add(new Bread());
Ingredients.Add(new Mayonnaise());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Turkey());
Ingredients.Add(new Turkey());
Ingredients.Add(new Bread());
}
}
Whenever we create an object of class TurkeySandwich
, we can call CreateIngredients()
to create the correct amount and order of ingredients for this sandwich.
But what if we wanted to go... bigger?
This is a Dagwood sandwich, named after a comic strip character who was fond of making them. In essence, a Dagwood is a ridiculously large sandwich with a great many layers.
We want to create a class to represent a Dagwood. What makes this patterns is that with our Factory Method, all we need to do is instantiate a class and override the CreateIngredients()
method, like so:
/// <summary>
/// Concrete Creator
/// </summary>
class Dagwood : Sandwich //OM NOM NOM
{
public override void CreateIngredients()
{
Ingredients.Add(new Bread());
Ingredients.Add(new Turkey());
Ingredients.Add(new Turkey());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Mayonnaise());
Ingredients.Add(new Bread());
Ingredients.Add(new Turkey());
Ingredients.Add(new Turkey());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Mayonnaise());
Ingredients.Add(new Bread());
Ingredients.Add(new Turkey());
Ingredients.Add(new Turkey());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Mayonnaise());
Ingredients.Add(new Bread());
Ingredients.Add(new Turkey());
Ingredients.Add(new Turkey());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Mayonnaise());
Ingredients.Add(new Bread());
Ingredients.Add(new Turkey());
Ingredients.Add(new Turkey());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Mayonnaise());
Ingredients.Add(new Bread());
Ingredients.Add(new Turkey());
Ingredients.Add(new Turkey());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Lettuce());
Ingredients.Add(new Mayonnaise());
Ingredients.Add(new Bread());
}
}
Now, when we want to create objects of type TurkeySandwich
or Dagwood
, we simply call them like this:
class Program
{
static void Main(string[] args)
{
var turkeySandwich = new TurkeySandwich();
var dagwood = new Dagwood();
//Do something with these sandwiches (like, say, eat them).
...
}
}
Will I Ever Use This Pattern?
Absolutely. The Factory Method pattern is exceedingly common in today's software design world. Any time you need to create groups of related objects, Factory Method is one of the cleanest ways to do so.
Summary
The Factory Method pattern provides a manner in which we can instantiate objects, but the details of the creation of those instance are left to be defined by the instance classes themselves.
Now, let's go eat some sandwiches!
Happy Coding!