Introduction to Factory Pattern (2): Factory Method
Contents
This post is also available in following languages
In my last article about Factory Pattern, a simple and intuitive method was introduced to encapsulate product creation logic without exposing details. The problem is that once we add a new concrete product call we have to modify the Factory class. It is not very flexible and requires the factory depending all concrete product types. Although class registration techniques can be used to eliminate the couplings in some extent, they still have some major drawbacks that prevent them to be used extensively.
In this post, we will explore the more popular Factory Method Pattern that solves the above problems.
Before looking at how to solve the problems, let’s first introduce Factory Method design pattern.
Factory Method Pattern
“Define an interface for creating an object, but let subclasses decide which class to instantiate. The Factory method lets a class defer instantiation it uses to subclasses.”
Factory Method lets a superclass specifies all standard and generic behavior using virtul “placeholders” for creation steps, and then delegates the creation details to subcleasses that are supplied by the client. In other words, factory methods uses an abstract method that encapsulate object creation logic, thus the new
operator which always creates an object is avoided.
Factory Methods are usually defined by an architectural framework, and then implemented by the user of the framework.
Above example shows a CarFactory
interface which has 3 concrete car factory types that implement CarFactory
. They are BmwCarFactory
, VolvoCarFactory
and TeslaCarFactory
, which produces BmwCar
, VolvoCar
and TeslaCar
respectively. The client SimpleFactoryDemo
asks a concrete car factory to create Car
, without the need of coupling the concrete car type.
Here is an example of the usage.
|
|
|
|
Above are the Car
and CarFactory
interfaces. Now let’s define the concrete product classes and their factories.
|
|
|
|
As you can see above, the concrete factory class returns the abstract Car
type instead of the concrete type.
Now let’s see how to use them in the client code.
|
|
As shown above, the factory returns an abstract Car
type, which is used afterwards. There is no need to couple the concrete product type to the client code.
Why use Factory Method Pattern?
The Factory Method Pattern is to solve the problem mentioned at the beginning of this article, which is the Simple Factory Pattern requires the factory to be updated whenever there is a new product type is added in the system.
So when to use a Factory Method Pattern instead of a Simple Factory Pattern? when your code requires multiple factory implementations. Each factory implementation implements the same factory interface, so that the products produced by the factories has the same abstract type, which makes the client code easy to switch factory implementations.
Pros and Cons?
Factory Method Pattern as explained above, has advantages in extensibility since it is more flexible in adding new types. It is a good example of open-closed principle in SOLID design principles.
Factory Method Pattern also has some drawbacks. As you might have noticed, factory method pattern requires you to create an interface for the Factory, and a factory implementation for each concrete factory. This leads to class explosions in amount when there are many types in a system.
Real Example
In Java, a good example is the iterator()
method in the collection API, which is well stated in this article. Each collection implements the interface Iterable<E>
, which defines a factory method iterator()
that returns an Iterator<E>
. An ArrayList<E>
is a collection. So, it implements the interface Iterable<E>
and overrides its factory method iterator()
which returns a subclass of Iterator<E>
.
Below is a simplifed definition of the Iterator<E>
interface from the Java source code:
|
|
Here is the factory interface:
|
|
Below is a simplified definition of ArrayList
from the java source code:
|
|
As you can see above, this shows a concrete factory that implements a factory method iterator()
. Note in actual Java source code, ArrayList
is derived from AbstractList
which is the one that implements the factory method pattern.
A typical use of the ArrayList
and its iterator looks like:
|
|
As shown above, the Iterator
the ArrayList
returns is an interface, thus the usage of it does not differ it from when getting from a LinkedList
, a HashMap
, a HashSet
or any other Collection type. This is the power of this pattern: you don’t need to know what type of collections you’re using, each collection implementation will provide an Iterator
through the factory method iterator()
.
Conclusion
Factory Method Pattern is a useful design pattern, when there are many concrete product types in the system, and may still be growing. Factory Method Pattern makes use of an abstract Factory interface and its factory method to have all concrete factory implementations produces the products with the same product type, thus encapsulates the producing details to the concrete factories themselves.
However, this pattern comes with the cost that it can expand the total number of classes in a system. Every concrete product class also requires a concrete factory class.
Author Gan Dong
LastMod 2019-10-06