Introduction
If you are a seasoned C#/Java application developer you should have used abstract factory pattern for sure. If you haven't...not to worry this idiot is here to help. When I started my coding days I did not realize the importance of this pattern initially, but thankfully my boss cum architect of the project was very particular about using certain design patterns in specific cases. So after bit of pushing myself I got the understanding and more importantly gained "where to use" sense regarding design patterns.
Among all the design patterns this could be termed as most important rather frequent one. Before going forward I would assume that as a reader you know what an Abstract class is in OOPS. If you are not much familiar with that then please help yourself by goggling it out.
Background
Design patterns come into rescue when try to solve some architectural problem in code. For example suppose in your application you have 3 different source of data - Webservices, Database and Excel import. Now when it comes to coding as a developer you need to take decision whether to write code separately for each data source or is there a way you could abstract the database type from the higher layer of the application, so that higher layer(Business logic/UI Layer) of the application doesn't need to worry whether the lower layers(Data layer) have changed or not.
So the pattern we are going to use today is a specialized one to solve this kind of problem by isolating and abstracting different "types" of databases from rest of the application.
Lets explore Using the code
So what does "Abstract Factory Pattern" do?
- It provides a generalized access point.
- It hides the details of the type, in our case database type from rest of the application.
Lets try to elucidate the 2nd point : So in our example instead of working through 3 different classes of connection 1. SQLConnection
2. ExcelConnection
3. WebServiceConnection
, we will only have one connection which will be visible to application layer i.e DataConnection class.
Problem statement and theoretical resolution
So we have 2 database one is Sql Server other one is Ole Db. Now we want to use Abstract Factory pattern in a way that our application layer doesn't have to have separate implementations when connection changes. Everything will be abstracted in data layer itself.
To use this pattern there are 3 basic steps we have to follow -
- Create an abstract class with the common properties/behavior.
- Inherit the abstract classes into the other classes which has detail of the implementations.
- Use factory pattern to get the Abstract type and perform concrete operations.
Step 1: Create an abstract class with the common properties/behavior.
At first lets create our Abstract class. So our AbstractDatabase abstract class has two properties
- Connection property (System.Data.Common.DBConnection)
- Command property (System.Data.Common.DBCommand)
public abstract class AbstractDatabase
{
public virtual DbConnection Connection { get; set; }
public virtual DbCommand Command { get; set; }
}
Step 2: Inherit the abstract classes into the other classes which has detail implementations.
Now as we know we cannot instantiate Abstract class. The instance classes would rather inherit it.
So for our SQLServerDatabase
class we will inherit from Database abstract class and Connection property will return SqlConnection
and Command
property will return SqlCommand.
The code snippet below is doing nothing but instantiating connection and command for SQLConnection.
public class SqlServerDatabase : AbstractDatabase
{
private DbConnection _connection = null;
private DbCommand _command = null;
public override DbConnection Connection
{
get
{
if(_connection == null)
{
_connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SqlServerConnection"].ConnectionString);
}
return _connection;
}
set
{
_connection = value;
}
}
public override DbCommand Command
{
get
{
if(_command == null)
{
_command = new SqlCommand();
_command.Connection = Connection;
}
return _command;
}
set
{
_command = value;
}
}
Now suppose as have an OleDB Connection datasource as well. For that we will create a new class OleDBDatabase
. It will inherit and implement our abstract class. Here connection property will return OleDBConnection
and command property will return OleDBCommand
.
In the same way as described above the below code snippet is only instantiating connection and command for OleDbConnection.
public class OleDbDatabase : AbstractDatabase
{
private DbConnection _connection = null;
private DbCommand _command = null;
public override DbConnection Connection
{
get
{
if(_connection == null)
{
_connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["OleDbServerConnection"].ConnectionString);
}
return _connection;
}
set
{
_connection = value;
}
}
public override DbCommand Command
{
get
{
if (_command == null)
{
_command = new OleDbCommand();
_command.Connection = Connection;
}
return _command;
}
set
{
_command = value;
}
}
}
Step 3: Use factory pattern to get the Abstract type and perform concrete operations.
Here we come to last step to implement our pattern. So how does it help us to hide the details from rest of the application?
Answer to that question would be - rest of the application doesn't directly deal with the OleDBDatabase
or SQLServerDatabase
class. Rather it deals with the abstract class and in this process factory pattern would help us to find the right implementation.
To demonstrate it I have created a small Forms Application which has two radio button. So the trick is whichever radio button you select it will only return that instance.
private void btnSelect_Click(object sender, EventArgs e)
{
AbstractDatabase database;
if (radSqlServer.Checked)
{
database = new OleDbDatabase();
}
else
{
database = new SqlServerDatabase();
}
}
Lets discuss the above snippet : In the button click
event we have selected the the database type. Type of database is abstract here. So when the higher layer of our application works with the database instance it need not know whether it is working with OleDb or SqlServer. It will simply work with the AbstractDatabase
type. You need not to train your mind much to see what is happening over here. Instead of using concrete type we are simply using Abstract type to hide implementation details from other part of app.
N.B : I have uploaded a solution file for your reference. It has quite the same code that we have explored in this article. While using the solution file please add your proper connectionstrings to the app.config file.
Real world application
So if you are developing an application which has
1. Multiple data sources.
2. Multiple output file format - for example you have to output your report to PDF,excel,word etc. But you don't want your other part of the app know how you are doing.
3. Any scenario where you have multiple input/output type but you could generalize it to one.
Advantage over concrete implementation
Let me give you a scenario in terms of our own example to understand the advantage of Abstract Factory Pattern. Suppose tomorrow a newer version of Oracle data source comes up and your mad client wants to use it in our application. What will you do then...will you rewrite the whole data layer application layer to accommodate the change?
Your answer would be no if you have used Abstract Factory pattern. You will only create a new concrete class which inherits from the Abstract database type and based on the selection you need to instantiate the OracleDataClient and you are good to go.
Happy coding guys. Will be more than happy to answer your questions