Factory Method
Define an interface for creating an object,but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
Last updated
Define an interface for creating an object,but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
Last updated
Factory Method provides an interface and method for creating an object in the class. But let its inheriting subclasses be able to override to specify which object will be created. Factory method assigns the creation of a specific object to a subclass
Creates a new way of initializing objects through a common interface
Hides the logic processing of the initialization method
Reduces complexity
Dependent, easy to extend
Reduces the possibility of compile errors
The Factory Method pattern suggests that you replace direct object construction calls (using the new
operator) with calls to a special factory method. Don’t worry: the objects are still created via the new
operator, but it’s being called from within the factory method. Objects returned by a factory method are often referred to as products.
At first glance, this change may look pointless: we just moved the constructor call from one part of the program to another. However, consider this: now you can override the factory method in a subclass and change the class of products being created by the method.
There’s a slight limitation though: subclasses may return different types of products only if these products have a common base class or interface. Also, the factory method in the base class should have its return type declared as this interface.
For example, both Truck
and Ship
classes should implement the Transport
interface, which declares a method called deliver
. Each class implements this method differently: trucks deliver cargo by land, ships deliver cargo by sea. The factory method in the RoadLogistics
class returns truck objects, whereas the factory method in the SeaLogistics
class returns ships.
The code that uses the factory method (often called the client code) doesn’t see a difference between the actual products returned by various subclasses. The client treats all the products as abstract Transport
. The client knows that all transport objects are supposed to have the deliver
method, but exactly how it works isn’t important to the client.
Components in the model:
Product : Defines an interface of objects that the factory method creates.
Concreteproduct: classes that implement the product template.
Creator: Declare a factory method, returning an object of type product. The Creator can also define a default implementation of the factory method whose return value is a default concreteproduct object. Call the factory method to create an object of type product.
ConcreteCrator: override factory method to return an instance of concreteproduct.
Hides the logic processing of the constructor
Limit dependencies between creator and concrete products
Easily expand and add new code to the program without breaking the original objects
Helps collect the code that creates the product into one place in the program, thus making it easier to track and manipulate.
Reduce the possibility of compile errors, in case we need to create an object and forget to declare a class, we can also handle errors in the Factory and declare the class for them later.
=> Because of the above characteristics, the factory pattern is often used in libraries (the user achieves the purpose of creating a new object and does not need to care about how it is created).
The source code can become more complex than usual because it requires the use of multiple classes to implement this pattern.
Refactoring an existing normal class into a class with a Factory Method can lead to many errors in the system, disrupting the existence of clients.
Factory method pattern depends on the use of private constructors so classes cannot be extended and inherited
Make all products follow the same interface. This interface should declare methods that make sense in every product.
Add an empty factory method inside the creator class. The return type of the method should match the common product interface.
In the creator’s code find all references to product constructors. One by one, replace them with calls to the factory method, while extracting the product creation code into the factory method.
You might need to add a temporary parameter to the factory method to control the type of returned product.
At this point, the code of the factory method may look pretty ugly. It may have a large switch
statement that picks which product class to instantiate. But don’t worry, we’ll fix it soon enough.
Now, create a set of creator subclasses for each type of product listed in the factory method. Override the factory method in the subclasses and extract the appropriate bits of construction code from the base method.
If there are too many product types and it doesn’t make sense to create subclasses for all of them, you can reuse the control parameter from the base class in subclasses.
For instance, imagine that you have the following hierarchy of classes: the base Mail
class with a couple of subclasses: AirMail
and GroundMail
; the Transport
classes are Plane
, Truck
and Train
. While the AirMail
class only uses Plane
objects, GroundMail
may work with both Truck
and Train
objects. You can create a new subclass (say TrainMail
) to handle both cases, but there’s another option. The client code can pass an argument to the factory method of the GroundMail
class to control which product it wants to receive.
If, after all of the extractions, the base factory method has become empty, you can make it abstract. If there’s something left, you can make it a default behavior of the method
We have a super class with many subclasses and based on the input we need to return a subclass. This model helps us put the responsibility of initializing a class from the user (client) side to the Factory class, helping to save system resources because of reusing existing objects instead of rebuilding each one. section with additional product
We don't know what subclasses we will need later. When you need to expand, create a sub class and implement a factory method for initializing this sub class.
Abstract factory: often used with factory method
Prototypes: does not require subclassing from creator. However, they often require initialization on the product class. Creator uses Initialize to initialize the object.