The abstract factory pattern is one level higher abstraction than factory method pattern because, the factory not just knows how to create instance for a single concrete class but the family of classes (Product of classes). So, there will be a common interface which will be derived by all the factories. Then the factory will create instance for classes which are from same family and return an object which is derived from a particular interface.
So, all factories will be derived from a common interface (something like IFactory), and all the sub classes for those factories (the classes for which the factory create instance) are derived from another common interface (something like IConcrete). Then the factory will create instance for those concrete classes and return objects in type IConcrete. Which IFactory you want to use, that you can configure in app.config or you can find it dynamic based on the business need.
For example, consider you have data in different data source such as Sql Server and Oracle. You want to collect data in any one of the datasource based on the business neeed.Below is the example which is implementd by Abstract Factory Pattern.
Here, IDataSourceFactory is the common interface implemented by SqlDataSourceFactory and OracleDataSourceFactory. If you choose SqlDataSourceFactory, then your data will be fetch from Sql. Otherwise it will come from oracle.
We have repositories for CustomerInfo and AccountInfo such as CustomerInfoSqlRepository, AccountInfoSqlRepository to fetch from Sql Server. CustomerInfoOracleRepository, AccountInfoOracleRepository for Oracle.
All these 4 repositories are derived from a common interface called "IRepository".So, both Sql Server and Oracle data sourcefactory will return object with the type of IRepository. Below example may help you understand clear.
Benefits:
Support extensibility without affecting the existing functionality.
Single responsibility principle, open close principles, Separation of concerns can be achieved.
Client applications will be working with interfaces instead of concrete classes which provides loose coupling between the client and target
class Program
{
static void Main(string[] args)
{
IDataSourceFactory dataSourceFactory = LoadFactory();
IRepository customerRepository = dataSourceFactory.CreateCustomerInfoRepository();
Console.WriteLine(customerRepository.GetDetail());
IRepository accountRepository = dataSourceFactory.CreateAccountInfoRepository();
Console.WriteLine(accountRepository.GetDetail());
Console.Read();
}
private static IDataSourceFactory LoadFactory()
{
//This can be configured in App.Config
return new SQLServerDataSourceFactory();
}
}
public interface IDataSourceFactory
{
IRepository CreateCustomerInfoRepository();
IRepository CreateAccountInfoRepository();
}
public class OracleDataSourceFactory : IDataSourceFactory
{
public IRepository CreateCustomerInfoRepository()
{
return new CustomerInfoOracleRepository();
}
public IRepository CreateAccountInfoRepository()
{
return new AccountInfoOracleRepository();
}
}
public class SQLServerDataSourceFactory : IDataSourceFactory
{
public IRepository CreateCustomerInfoRepository()
{
return new CustomerInfoSqlRepository();
}
public IRepository CreateAccountInfoRepository()
{
return new AccountInfoSqlRepository();
}
}
public class AccountInfoSqlRepository : IRepository
{
public string GetDetail()
{
return "Account information received from Sql Server repository";
}
}
public class CustomerInfoSqlRepository : IRepository
{
public string GetDetail()
{
return "Customer information received from Sql Server repository";
}
}
public class AccountInfoOracleRepository : IRepository
{
public string GetDetail()
{
return "Account information received from Oracle repository";
}
}
public class CustomerInfoOracleRepository : IRepository
{
public string GetDetail()
{
return "Customer information received from Oracle repository";
}
}