Design patterns are the way we organize the structure of our classes in our applications, not only to reduce the code complexity but also to make it re-usable and an optimized code.
There are around 23 design patterns in .NET, that are considered to be the base of other patterns (Not sure about any more than 23 though) . They are divided into 3 main categories. These are :
- Creational Patterns
- Structural Patterns
- Behavioral Patterns
I will be discussing the Factory pattern here which comes under the category of Creational Patterns. There is one another pattern called Abstract Factory in this category, which is different in concept, but name sounds similar to the Factory pattern. So not to confuse with it, I will be discussing the Factory pattern here, with simple example.
To explain this pattern in a simple way, this patterns contains a Base class or a factory class you can say, which acts as an intermediate between the client (UI in our example) and the Rest of all the other classes. The client simply makes a call to the Factory class which decides the rest of point of calling appropriate function from the appropriate class.
To explain in detail, let’s take an example :
Without Factory Pattern :
We have 2 derived classes from a Base class, which implement a method GetString(), to create their own versions. Now, when we need to call this method, the user will be required to instances of both the classes to call the particular class method i.e. the user will be required to do something like :
ClassA objClassA = new ClassA();
ClassB objClassB = new ClassB();
It will produce the required result but the point here is that the user/client has to create a specific Class type instance to call its respective method. Further, what if there is another version of this method in a new ClassC class in future, added here. Then the user will be required to create an instance of type ClassC here.
With Factory Pattern :
With factory pattern, we will be simply adding the responsibility of calling the required method on our Factory, which will return appropriate instance type and call its corresponding function. Let’s create a sample here :
- Create a new Project using the visual studio, and add following 4 classes :
- IFactoryBase.cs : The interface of the Factory which contains the common method to be implemented by the derived classes.
- Factory.cs : Which returns the appropriate instance type to the client .
- ClassA.cs : Contains one version of the IFactory method implemented in it.
- ClassB.cs : Contains second version of the IFactory method implemented in it.
Define a common method(GetString() in this example) in IFactory which will be implemented by ClassA and ClassB according to their requirements.
- In Factory.cs class, add a new method which will take an input parameter and return an instance of the thype IFactory type. Based on the input by the client (or UI), an instance of ClassA or ClassB will be returned. Since both Classes A and B derive from the IFactory type, we can return their instances encapsulated in the IFactory type from this method
- At the front end or the UI, we will take an input from the user, either 1 or 2. It will call the above Factory method and the instance type of the either class will be returned from the method, as the logic is descirbed in above figure.
- Now run the application and enter 1 or 2 in the textbox and click the button.
- As we have entered 1 in the textbox, the Factory method will return the instance type of ClassA in IFactory. When the call is made to the GetString() method, it will call the method in the ClassA, as the IFactory instance iFactoryType contains the reference of the ClassA type here. Similarly, when we enter 2 here, it will call the ClassB method here.
One more advantage that this pattern provides is that, in case the number of classes is too large, then it becomes more complex as the user has to add the conditions like If-Else to decided which class object should be called and especially if it has to be done a 3-4 places in the code, it results in redundant & complex code. With this pattern, it can be moved in to the Factory method, where this If-Else method will be created only once. Thus reducing the complexity and organizing the code in proper way. Hope this clears the basic idea behind the Factory design pattern.