Introduction
This article reveals some good use of design patterns using generics. Think if these design patterns are made using generics in .NET, it can work as wonders. You can create your own design pattern class library which could be then made re-usable in any project. I will be showing Factory Design Pattern using generics in .NET.
Background
For those who don't know Factory Design Pattern, please refer to this article of GOF available at below mentioned link:
Using the Code
Now let's start with some coding stuff. First, I will show you the implementation of Factory pattern without using generics. Then, we will go about changing the same factory pattern using generics and you will see the difference. So, we start with creating two simple classes, i.e., ReportGenerator
and ReportAnalyser
which share a common interface implementation IActivity
.
NOTE: I have taken ReportGenerator
and ReportAnalyser
classes for example purposes only.
public interface IDBActivity
{
void Process();
}
public class Enumeration
{
public enum ModuleName
{
ReportGenerator = 1,
ReportAnalyser = 2
}
}
public class ReportGenerator : IActivity
{
public void Process()
{
}
}
public class ReportAnalyser : IActivity
{
public void Process()
{
}
}
Now comes the implementation of Factory Pattern. To achieve this, let's create a class FactoryClass
.
public class FactoryClass
{
public static IActivity CreateInstance(Enumeration.ModuleName enumModuleName)
{
IActivity objActivity = null;
switch (enumModuleName)
{
case Enumeration.ModuleName.ReportGenerator:
objActivity = new ReportGenerator();
break;
case Enumeration.ModuleName.ReportAnalyser:
objActivity = new ReportAnalyser();
break;
default:
break;
}
return objActivity;
}
}
From the above code, we are creating an instance of ReportGenerator
or ReportAnalyser
class as per enum
value passed and assigning it to IActivity
object. Hence, when client will call CreateInstance
method, it will just receive IActivity
object rather than ReportGenerator
or ReportAnalyser
object.
This is what we call core of Factory Pattern where client is creating objects of ReportGenerator
or ReportAnalyser
without specifying exact class of the object. The below code snippet shows how client will use Factory Pattern by calling our FactoryClass
' CreateInstance()
method.
private void btnProcess_Click(object sender, EventArgs e)
{
IActivity objActivity = null;
objActivity = FactoryClass.CreateInstance(Enumeration.ModuleName.ReportGenerator);
objActivity.Process();
}
Now comes the important part of this article where I will be showing you how to use generics within Factory Pattern. Okay, let's first create a new Windows
class library project and name it as DesignPatterns
. Within that project, create a new class and name it FactoryPattern
.
Inside that class, please write the code as mentioned below:
public class FactoryPattern <K,T>
where T : class, K, new()
{
public static K CreateInstance()
{
K objK;
objK = new T();
return objK;
}
}
You might be wondering what's all this ??? :-). Okay, I will explain the concept to you. Here, I have created FactoryPattern
class using generics. It takes two parameters, i.e., "K
" and "T
". T
parameter has "where
" constraint which depicts that T
should be a class, it should be inherited from K
and its instance can be created. Huh ... too much of conceptual. Let's analyze this line where T : class, K, new()
:
- where
T
:- means you want some constraints to be implemented when client passes T
as a type parameter
class
:- means that T
parameter passed should be a class
K
:- means that T
parameter passed which is a class should always be inherited from K
type parameter
new()
:- means that you can create instance of T
parameter passed in FactoryPattern
class
I believe this makes sense and things are now more clear. So now I know the question that will be coming in your mind is how to fit this class in Factory Pattern implementation?? You just need to make some changes in the code written in FactoryClass
.
Please find the below code snippet which will make things more clear:
public class FactoryClass
{
public static IActivity CreateInstance(Enumeration.ModuleName enumModuleName)
{
IActivity objActivity = null;
switch (enumModuleName)
{
case Enumeration.ModuleName.ReportGenerator:
objActivity = FactoryPattern<IActivity,
ReportGenerator>.CreateInstance();
break;
case Enumeration.ModuleName.ReportAnalyser:
objActivity = FactoryPattern<IActivity,
ReportAnalyser>.CreateInstance();
break;
default:
break;
}
return objActivity;
}
}
All that is using generics with Factory Pattern. Now can you figure out the meaning of the line where T : class, K, new()
.
ReportGenerator
is a class. It is inherited from IActivity
interface. You can create an instance of ReportGenerator
class. Since you have created FactoryPattern
class using generics and construction logic of objects all lies at central point, you can now use your
FactoryPattern
class in all your future projects. You need not have to think / worry about the creation of object, just pass the appropriate parameters and the object is created in FactoryPattern
class.
Think about other Design Patterns you can implement using Generics... sounds challenging !!
I hope this article will be of some use to you.. Since this is my first article, I could have made mistakes, if so, then kindly rectify it.
You can download the source code. It's developed in .NET 3.5.