Factory Method is a creational design pattern that provides an interface for creating objects in superclass, but allow subclasses to alter the type of objects that will be created.
Imagine that you are creating a logistics management application. The first version of your app can handle only transportation by trucks, so the bulk of your code lives in a
After a while, your app becomes so popular that you get tons of requests to include sea transportation as well.
Great news, right?! But how about the code? It looks that most of your code is coupled to the
Truck class. Adding
Ships would require making changes to the entire codebase. Moreover, if you decide to add another type of transportation to the app, you will probably need to make all of those change again.
You will end up with nasty code riddled with conditionals, which select behaviors depending on classes of transport objects.
The Factory Method pattern suggests replacing direct object creation (using a
new operator) with a call to a special "factory" method. The constructor call should be moved inside that method. Objects returned by factory methods are often referred to as "products."
At first glance, such move may seem pointless. But now you can override the factory method in a subclass and change the class of an object that will be created. Let's see how it works:
Of course, there is slight limitation: all products must have a common interface (say,
Transport). Factory method in a base class should be returning this common interface.
Subclasses may return different concrete products as long as these products have a common base class or interface (for example, both
Ship implement the
Clients of a factory method do not care about the particular type of a product they receive. They work with all products using a common product interface.
Product declares the single interface for all objects that can be produced by the creator and its subclasses.
Concrete Products are the different implementations of the Product interface.
Concrete Creators will create and return instances of these classes.
Creator declares a factory method that returns the Product type. This method can either be abstract or have some default implementation. In the first case, all Concrete Creators must implement their factory methods.
Despite the name, in the real world, the product creation is not the main responsibility of a Creator class. Usually, it has some core business logic that works with Products.
Here is the analogy: a large software development company can have a training department for programmers. But the primary function of the company is still writing code.
Concrete Creators implement or override the base factory method, by creating and returning one of the Concrete Products.
Note that a factory method does not have to create new instances all the time. It can also return existing objects from some cache, etc.
This example illustrates how Factory Method can be used for creating cross-platform UI elements. The factory method is declared in the base UI dialogue class. It returns abstract buttons. The dialog subclasses override the factory method by returning particular variations of buttons.
The result is used in the base dialog's code to compose a UI window. The dialog works with buttons through their common interface. So whichever type of buttons the factory method returns, the dialog code remains functional.
Therefore, the Factory Method pattern makes the primary code of a class independent from the concrete classes of products it uses. Factory Method makes subclasses responsible for choosing concrete classes of products that will be created.
When you do not know the exact types and dependencies of the objects, your code should work with.
For instance, reading and writing data from multiple sources—file system, database or network. All of these sources would have different types, dependencies and initialization code.
Factory method can hide the implementation details of a product from the other code. To support a new product type, you will only need to create a new subclass and override the factory method in it.
When you want to provide users of your library or framework with a way to extend its internal components.
A user can easily subclass some particular component. But how would the framework recognize that subclass and work with it instead of a standard component? A user will have to override every single method that creates instances of standard components and change them to create objects of a custom subclass. That is pretty awkward, isn't it?
The better solution would be to not only give a user means to extend particular classes, but also reduce the code that produces components to a single creational method. In other words, to provide the factory methods.
Let's see how it would work. Imagine that you write an app using an open source UI framework. Your app must have round buttons, but the framework provides only square ones.
The first thing that you do is implement the
RoundButton class. But now you need to tell the main
UIFramework class to use the new button class instead of a default one.
To achieve this, you create a subclass
UIWithRoundButtons from a base framework class and override its method
createButton. This method still returns
Button objects in a base class, but your new subclass produces
RoundButtons objects. Now, in your app, you must initialize the framework using
UIWithRoundButtons class instead of
UIFramework. And that is about it!
When you want to save system resources and reuse existing objects, instead of rebuilding new ones.
For example, when dealing with large or resource-intensive objects like database connections, etc.
Imagine how much has to be done to reuse existing objects:
- First, you will need to create a pool for keeping the existing objects.
- When someone requests an object, you will look for a free object inside that pool.
- ...and return it to the client code.
- Only if there are no free objects, you will create a new one (and add it to the pool).
This code must be placed somewhere. The most convenient place is a constructor. This way all of those checks will be executed whenever someone tries to create an object. But alas, constructors must return new objects by definition, so they can not return existing instances.
On the other hand, client code, which uses your objects, can not contain it either. Otherwise, it would know too much implementation details of your class. Therefore, you need to have a single method for encapsulating this logic. That would be a factory method.
How to Implement
Extract the common interface for all products. This interface should declare methods that make sense for every product.
Add an empty factory method inside the creator class. Its signature should return the product interface type.
Go over the creator's code and find all references to product constructors. One by one, replace them with calls to the factory method but extract product creation code to the factory method.
You might need to add a temporary parameter to the factory method that will be used to control which product will be created.
At this point, the factory method's code may look pretty ugly. It may have a large switch operator that picks which product class will be instantiated. But do not worry, we will fix it right away.
Now, override the factory method in subclasses and move there the appropriate case from the switch operator in the base method.
The control parameter used in the base creator's class can also be used in subclasses.
For instance, you may have a creator's hierarchy with a base class
Ground, plus the product classes:
Planejust fine, but
Trainat the same time. You can create a new subclass to handle both cases, but there is another option. The client code can pass an argument to the factory method of the
Groundclass to control which product it receives.
If the base factory method has become empty after all moves, you can make it abstract.
Pros and Cons
- Follows the Open/Closed Principle.
- Avoids tight coupling between concrete products and code that uses them.
- Simplifies code due to moving all creational code to one place.
- Simplifies adding new products to the program.
- Requires extra subclasses.
Relations with Other Patterns
Often, designs start out using Factory Method (less complicated, more customizable via subclasses) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, but more complex) as the designer discovers where more flexibility is needed.
- If you can not figure out the difference between various factory patterns and concepts, then read our Factory Comparison guide.