Factory Method Pattern in C#
Originally posted here
The Factory Method is a creational design pattern that allows the abstraction of object creation. It defines a method for creating an instance based on a superclass but allows subclasses to alter the type of objects that they create.
You can find the example code of this post, on GitHub.
Conceptualizing the Problem
Imagine that we are working for a logistics company that hired us to create a logistics management application. The company is small and has some trucks to handle transportation. Thus our application can only transport goods via truck, and the bulk of our code lives inside the Truck class.
Thanks to our application the company gains traction and growing exponentially. Eventually, the company buys a cargo ship and now wants us to incorporate sea logistics into the app.
That's great news, but how about the code? Currently, most of the code is coupled to the Truck class. Adding a Ship class into the application would require architectural-level changes to the entire codebase. Moreover, if later we need to add another type of transportation to the application, we will probably need to make all of these changes again.
As a result, we will end up with a nasty codebase, riddled with conditionals that alter the application's behaviour depending on the transportation mode.
The Factory Method pattern suggests that we should replace direct object construction calls (using the `new` operator) with calls to a factory method. Objects returned by a factory method are often referred to as products.
Initially, this change does not make any sense: we just moved the constructor call from one part of the code to another. However, now we can override the factory method in a subclass and change the products being created by the method.
There's a limitation though: subclasses may be able to return different types of products, but these products must have a common base class or interface.
Back to our logistics application, both Truck and Ship classes must implement a common interface, for example, ITransport, which declares a method called Deliver. The classes can implement the interface differently: the Truck class is concerned with cargo delivery by land, while the Ship class is concerned with cargo delivery by sea.
The client using the factory method does not see a difference between the actual products returned by each subclass. The client treats all the products as abstract ITransport objects. The client also knows that all ITransport objects must implement some Deliver method, but how each of them implements it doesn't matter.
Structuring the Factory Method Pattern
In its base implementation, the Factory Method pattern has four participants:
To demonstrate how the Factory Method pattern works, we are going to create...a sandwich. According to Wikipedia:
A sandwich is a food typically consisting of vegetables, sliced cheese or meat, placed on or between slices of bread, or more generally any dish wherein bread serves as a container or wrapper for another food type.
To start, we will implement some Product participants, which will be the ingredients that comprise the sandwiches. We'll create an abstract Ingredient class to represent them:
Now let's instantiate a few classes to represent ingredients in sandwiches (our CocreteProduct participants):
What we want to do now is to create 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:
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 to the ConcreteCreator classes that we now need to define. Let's start with a Reuben sandwich:
Whenever we create an object of class ReubenSandwich, we can call CreateIngredients()` to create the correct amount and order of ingredients for this sandwich.
Let's create a GrilledCheeseSandwich now:
Now we can create the sandwich in our Main method:
And as always, the output of this method will be the following:
Comparison of Different Factories
There are different references to the term Factory around the web. Though they might look as all referring to the same thing, they all have different meanings.
Let's try to figure out their differences.
Recommended by LinkedIn
Factory
The Factory is an ambiguous term that causes the most confusion. This term stands for a function method or class that is supposed to be producing something. Most commonly, factories produce objects. But they can also produce files, records to a database, logs, etc.
Any of the following can be referred to as a factory:
When someone uses the factory, the meaning of it is supposed to be clear from the context, but still causes headaches and confusion, especially in legacy codebases.
Creation Method
Joshua Kerievsky defines a Creation Method as a method that creates objects. This means that every result of a factory method pattern is a creation method but not necessarily the reverse. It also means that we can substitute the term creation method wherever Martin Fowler uses the term factory method in Refactoring.
In reality, the creation method is just a wrapper around a constructor call. It may just have a name that better expresses our intentions. On the other hand, it may help to isolate the code from changes to the constructor. It could even contain some particular business logic that would return existing objects instead of creating new ones.
A lot of people call this method a factory method just because it creates new objects. The logic is straightforward. The method creates objects and since all factories create objects, this method is a factory method. As a consequence, there's a lot of confusion between creation methods and factory methods.
The following Next method is a creation method:
Static Creation Method
A Static Creation Method is a creation method declared as static.
While many people call these static creation methods. That is wrong. The Factory Method is a design pattern based on inheritance. If you make it static, you can no longer extend it via subclassing, which defeats the purpose of the pattern.
When a static creation method returns a new object, it becomes an alternative constructor.
This might be helpful when:
In the following example, the Load method is a static creation method. It provides a convenient way to retrieve users from a database.
Simple Factory Method
The Simple Factory describes a class that has a single creation method with a large conditional, that decides the product class based on the method parameters.
Simple factories are usually confused with general factories or with one of the creational design patterns. In most cases, a simple factory is an intermediate step in introducing the Factory Method or Abstract Factory patterns.
A simple factory is usually represented by a single method in a single class. Over time, this method might become too big, so we might decide to extract parts of the method into subclasses. Once we do it several times, the whole thing will turn into the classic factory method pattern.
Here's an example of a simple factory:
Factory Method Pattern
The Factory Method is a creational design pattern that provides an interface for creating objects but allows subclasses to alter the type of object that will be created.
If you have a creation method in the superclass and several subclasses that extend it, you probably have a factory method in your hands.
Abstract Factory Pattern
The Abstract Factory is a creational design pattern that allows producing families of related or dependent objects without specifying their concrete classes.
For instance the classes Transport, Engine and Controls. There are might be several variants like Car, CombustionEngine and SteeringWheel or Ship, Waterjet Engine and Helm.
If you don't operate with product families, then you don't need an abstract factory.
A lot of people mix up the abstract factory pattern with a simple factory class declared as abstract. Don't do that.
Pros and Cons of Factory Method Pattern
Relations with Other Patterns
Final Thoughts
In this article, we have discussed what is the Factory Method pattern, when to use it and what are the pros and cons of using this design pattern. We also examined different types of factories and how the Factory Method pattern relates to other classic design patterns.
The Factory Method design pattern lets us leave the type of created object on the subclasses.
It enables us to define an interface through which the client will create the object. Its main purpose is to hide the object creation logic from the client. It is also known as a virtual constructor.
It's worth noting that the Factory Method pattern, along with the rest of the design patterns presented by the Gang of Four, is not a panacea or a be-all-end-all solution when designing an application. Once again it's up to the engineers to consider when to use a specific pattern. After all these patterns are useful when used as a precision tool, not a sledgehammer.