Factory Method Pattern is a creational pattern.
In a framework, we generally have classes representing abstractions and framework needs to manage relationships between objects of these classes, and also creation of these objects. Clients extend these abstract classes for specific implementations. Problem here is that framework only knows abstract classes and not their concrete implementations.
Factory Method Pattern provides a solution to this problem. This pattern allows us to define an interface to create an object, but lets subclasses decide how to implement the interface, thus deferring instantiation to subclasses.
It encapsulates the knowledge of which specific implementations needs to be instantiated and moves this knowledge out of the framework.
It encapsulates the knowledge of which specific implementations needs to be instantiated and moves this knowledge out of the framework.
Factory Method approach
An abstract method is defined in the abstract creator class. This method is supposed to have the responsibility of creating instances of appropriate product classes. Subclasses of abstract creator class then implement this method to implement creation of instances of specific products.
We use Factory Method pattern when:
- A class don't know about specific implementations it need to instantiate
- A class wants its subclasses to decide which type of objects to be instantiated
Code structure
Code structure we need to implement Factory Method pattern is as follows:
We define an abstract class Creator which contains an abstract factory method. This factory method has contract of returning an instance of type Product, which is another abstract class.
In subclass of Creator, like CreaotrA and CreatorB, we implement the factory method. Specific implementation creates instance of specific implementation of Product, like ProductA or ProductB.
Consequence of this code structure is that client code(like 'someOperation' method in Creator) is decoupled from concrete implementations of Product as well as creation logic, and it has to deal only with Product interface. Subclasses of Creator are in full control of which type of Product to create without client code being impacted if there are any changes in creation logic.
Basically what we achieve here is to separate object creation logic from the code which uses that object. So down the line object creation knowledge may undergo a change but client code is decoupled from this change. This makes client code adhere to 'O' of SOLID principles.
Also, factory method pattern is one of the way we can implement 'D' of SOLID principles. As now high level component('someOperation' in Creator) does not depend on low level component(different implementations of Product), instead both now depend on abstraction(Product), and thus it introduces 'Dependency Inversion' in our code.
We can have factory method parametrized. This means that method would take an input parameter and use it to decide which product to create. It's a good practice to use enums as parameters to make sure that parameters are type safe.
Parallel class hierarchies
Another way of looking at it is that we encapsulate creation knowledge of a certain type of products into their respective creator. This helps in maintaining parallel class hierarchies. For example, in above UML diagram CreatorA is responsible for creating instances of ProductA, while CreatorB is reposnsible for creating instances of ProductB. Both creators are subclasses of Creator while both products are subclasses of Product. So we have two parallel class hierarchies evolving here and factory method is the connection between them.
What we may not like about Factory Method?
If a new type of Product has to be instantiated and existing Creator implementations are not a good fit to create it, then we may have to create a new Creator subclass for it. This is a bit of overhead just to instantiate a new type of Product.
No comments:
Post a Comment