Hi guys! Today, I talk about the Factory Method Design Pattern.
Factory method is a creational design pattern its main goal is to provide an interface to create objects. The pattern tells us to have a common Interface o Superclass where declare a method to create objects and concrete subclasses that implement or inherent to them.
- Unsure which concrete implementation of an Interface I want to return –> I can return many concrete classes that implement the same interface
- Separate the object creation in another structure
- Lots of if/else blocks and switch statements when deciding which concrete class to create
To understand this pattern we’ll work with a specific problem, it’s a real-life problem:
We need to build an Access Control System. For that, the customer gave us three access control devices. These devices are used to check the schedule of employees.
For example, Sam must be in this Local at 5 pm and go out at 11 pm. When Sam arrives at the Local put your finger in the access control and this operation will generate an attendance in the internal database of the device.
Ok, these are our devices:
- ZK Access control
- Lg Access Control
- Hp Access Control
For this example, we supposed that these devices have two operations:
- GetUsers() : Get registered users from the access control
- GetAttendances(): Get attendances from the access control.
The customer told me, “Hey, Fran maybe in the future we will buy new access control devices, please build a scalable solution”
Note: Each access control can implement these operations how they want it.
- Zk has a public API to consult users and attendances. Return a nice JSON result.
- Lg writes in a specific text document in the server and then we need to connect a third-party system to access to that information. Return a string result and then we must parse this data.
- Hp access control doesn’t have a public API for this reason, we must comply with a specific protocol to retrieve data. Return a XML result.
All these points are required to interact with each device. It is the responsibility for each device to comply with own protocol in each specific access control concrete class.
In other words, they must implement the operations: GetUsers() &GetAttendances() in accordance with their necessities.
Solution One – Code fast 🙁
Ok, we have access controls and all have two specific operations. Ok, this first part sounds an Interface.
For this reason, we’ ll create an IAccessControl Interface and it has the 2 operation methods.
For another hand, we need 3 concrete classes:
- NullAccessControl –> A bonus – Null object pattern :p
We have this class diagram:
The main problem is the switch statement. The main class has business logic and creational object responsibility. When we need to add another AccessControl we must modify this class: No comply with the Open / Closed Principle.
Solution Two – Simple Factory 🙂
For this alternative, we try to improve the previous solution.
First, we encapsulate the creation responsibility in a specific object: AccessControlFactory –> Separation of concern principle!
Then, we delete the switch statement for that we use REFLECTION
–> Color note: Reflection & The Factory Method are great friends!
After I do the refactoring, we can see this class diagram:
We can see: the concrete access control classes implement IAccessControl Interface
- The main Program class doesn’t know any access control concrete classes, just the interface IAccessControl.
- To get an Access Control, the program class use the AccessControlFactory Class.
- The AccessControlFactory class has a dictionary of key and classType. This allows does a dynamic instantiation using reflection.
The AccessControlFactory class has the magic.
- The constructor load type using Reflection –> Get types from the current assembly and load with these the dictionary
- When we create an instance of an AccessControl, CreateInstance method receives an access control code like a parameter with it gets the type from the dictionary and finally, instance the concrete class that implements IAccessControl Interface.
Final Solution- Factory Method 😀
Even though the previous solution sounds great has a few issues:
- Use a concrete Factory Method class
- We should split the object creation to multiple factories that implement the same Factory Interface
The factory method design pattern:
- Not use a Concrete class to Factory –> Use an Interface or abstract class
- Delegate object creation to multiple factories that share a common Factory Interface
- Derived factory classes implement or override the factory method of the base.
Implementing the Factory Pattern in our problem:
We can see:
- Program class load all factories using reflection in a dictionary.
- Program class can instantiate a specific Factory class using reflection.
- Program class only interact with IAccessControlFactory, it doesn’t know any concrete factory class.
- IAccessControFactory is our Main Factory Interface and it’s implemented for HpAccessControlFactory, LgAccessControlFactory and ZkAccessControlFactory.
- Each Concrete Access Control Factory must instantiate its Concrete Access Control Class in the method GetInstance.
- Each Concrete Access Control Class implement a common interface: IAccessControl
Factory Pattern is a great creational design pattern! It’s really useful to separate the object creation in another specific object.
Comply with the Open/Closed and Separation of Concern Principles.
Normally, you can mix it with the Singleton Pattern.
Factories in .NET commonly make use of REFLECTION.
Complete code on my GitHub: https://github.com/morales-franco/DesignPatterns