Abstract Factory pattern is used to create concrete class instances without specifying the exact class type (i.e. to create instance of a classes without specifying the exact class type). Abstract Factory Pattern is one of the Creational Design Patterns. Creational Design patterns are design patterns that handle object creation mechanisms.
The Abstract Factory Pattern Structure
1. Abstract Factory: Declares an interface that creates abstract objects.
2. Concrete Factory: Which implements the operations declared in the Abstract Factory. In Abstract Factory pattern, it may have multiple Concrete Factory classes.
3. Abstract Product: Declares an interface that creates abstract result objects.
4. Concrete Product: This will be the object created by the corresponding concrete factory. It implements the opreations declared in the Abstract Product.
5. Client: Client will use only interfaces as part of Abstract Factory and Abstract Product.
Intent
1. Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
2. A hierarchy that encapsulates: many possible “platforms”, and the construction of a suite of “products”.
3. The
new
operator considered harmful.Problem
If an application is to be portable, it needs to encapsulate platform dependencies. These “platforms” might include: windowing system, operating system, database, etc. Too often, this encapsulatation is not engineered in advance, and lots of
#ifdef
case statements with options for all currently supported platforms begin to procreate like rabbits throughout the code.Discussion
Provide a level of indirection that abstracts the creation of families of related or dependent objects without directly specifying their concrete classes. The “factory” object has the responsibility for providing creation services for the entire platform family. Clients never create platform objects directly, they ask the factory to do that for them.
This mechanism makes exchanging product families easy because the specific class of the factory object appears only once in the application - where it is instantiated. The application can wholesale replace the entire family of products simply by instantiating a different concrete instance of the abstract factory.
Because the service provided by the factory object is so pervasive, it is routinely implemented as a Singleton.
Structure
The Abstract Factory defines a Factory Method per product. Each Factory Method encapsulates the newoperator and the concrete, platform-specific, product classes. Each “platform” is then modeled with a Factory derived class.
Sample code in C#
Note: The following example does not cover the whole database functionality. It is just created to explain Abstract Factory pattern. Even though you can modify the code to accomplish the whole database functionality.
A Real world Example for Abstract Factory Pattern
1. First we will create an Abstract Product. The below code shows an interface ("IDatabaseHelper") which will act as an Abstract Product in our sample application.
public interface IDatabaseFactory
{
IDatabaseHelper CreateHelper();
}
Note: You can use either Inerface or an Abstract Class to create an Abstract Product.
2. Next we will create two Concrete Product which implements the Abstract Product. The classes "OracleDatabaseHelper" and "SqlDatabaseHelper" will be our Concrete Products in our sample application.
public class SqlDatabaseHelper : IDatabaseHelper
{
private System.Data.SqlClient.SqlConnection _connection;
public System.Data.IDataReader ExecuteReader()
{
//todo
return null;
}
public System.Data.DataSet ExecuteDataSet()
{
//todo
return null;
}
public int ExecuteNonQuery()
{
//todo
return 0;
}
public object ExecuteScalar()
{
//todo
return null;
}
public void OpenConnection()
{
_connection = new System.Data.SqlClient.SqlConnection();
//todo
}
public void CloseConnection()
{
_connection.Close();
//todo
}
}
public class OracleDatabaseHelper : IDatabaseHelper
{
System.Data.OleDb.OleDbConnection _connection;
public System.Data.IDataReader ExecuteReader()
{
//todo
return null;
}
public System.Data.DataSet ExecuteDataSet()
{
//todo
return null;
}
public int ExecuteNonQuery()
{
//todo
return 0;
}
public object ExecuteScalar()
{
//todo
return null;
}
public void OpenConnection()
{
_connection = new System.Data.OleDb.OleDbConnection();
//todo
}
public void CloseConnection()
{
_connection.Close();
//todo
}
}
3. Next we will create an Abstract Factory. Here "IDatabaseFactory" interface will be our Abstract Factory.
public interface IDatabaseFactory
{
IDatabaseHelper CreateHelper();
}
4. Next we will create a Concrete Factory which implements the Abstract Factory. Here "OracleDatabaseFactory" and "SqlDatabaseFactory" classes will act as Concrete Factory through our sample application.
Note: In Abstract Factory pattern, it is possible to have multiple Concrete Factory Classes which all implements the Abstract Factory.
Note: In Abstract Factory pattern, it is possible to have multiple Concrete Factory Classes which all implements the Abstract Factory.
public class SqlDatabaseFactory : IDatabaseFactory
{
public IDatabaseHelper CreateHelper()
{
return new SqlDatabaseHelper();
}
}
public class OracleDatabaseFactory : IDatabaseFactory
{
public IDatabaseHelper CreateHelper()
{
return new OracleDatabaseHelper();
}
}
5. Next we can create a Client, which will use the Abstract Factory and Abstract Product. Here in our example class "DatabaseClient" acts as a client.
public class DatabaseClient
{
private IDatabaseHelper _helper;
public DatabaseClient(IDatabaseFactory factory)
{
_helper = factory.CreateHelper();
//do any other code if needed.
}
public IDatabaseHelper Helper
{
get
{
return _helper;
}
}
}
To use the above pattern you can follow the following sample.
DatabaseClient dbClient = new DatabaseClient(new SqlDatabaseFactory());
dbClient.Helper.OpenConnection();
//do other operations
dbClient.Helper.ExecuteNonQuery();
//do other operations
dbClient.Helper.CloseConnection();
Posted By: Mr. Palash Paul