Factory Design Pattern vs Abstract Factory Design Pattern
Design patterns are powerful tools for building scalable and maintainable software. When it comes to Factory and Abstract Factory patterns, understanding their differences can get tricky if you learn one after the other. This blog offers a comparative approach to clarify their concepts and uses.
Let's start with the Factory Design Pattern.
Factory Design Pattern
The Factory Design Pattern provides an interface for creating objects, allowing subclasses to alter the type of objects that will be created.
In the UML diagram above, the IDbServerFactory
returns a DbServer
object based on the parameter passed by the user.
This approach abstracts the creation process, making it simple for clients. For instance, if new providers are integrated, the client code remains unchanged—it simply specifies the provider, and the factory handles the object creation.
Example Code:
Imagine a client (FactoryDesignPattern
) that needs an Azure DB server. By calling GetDbServer("azure")
, the desired server is created seamlessly.
using Contracts;
namespace FactoryDP.Services
{
public class FactoryDesignPattern : IDesignPattern
{
public object ExecuteDesignPattern()
{
IDbServerFactory dbServerFactory = new DbServerFactory();
var dbServer = dbServerFactory.GetDbServer("azure");
dbServer.SetupDatabse();
return (dbServer.GetType().ToString() + " Created");
}
}
}
Key Factory Components:
-
Factory Interface (
IDbServerFactory
): Defines a method to return aDbServer
instance. -
Concrete Factory (
DbServerFactory
): Implements logic to decide which specific object to create. -
Abstract Product (
DbServer
): Declares the interface for concrete products. -
Concrete Products (
AzureDbServer
,AwsDbServer
): Implement the product interface.
Sample Implementation:
namespace FactoryDP.Services
{
public interface IDbServerFactory
{
DbServer GetDbServer(string serverProvider);
}
public class DbServerFactory : IDbServerFactory
{
public DbServer GetDbServer(string serverProvider)
{
return serverProvider.ToLower() switch
{
"aws" => new AwsDbServer(),
"azure" => new AzureDbServer(),
_ => new AzureDbServer(),
};
}
}
}
By using this design, clients no longer need to manage the complexity of object creation.
Abstract Factory Design Pattern
If you have grasped the Factory pattern, it’s time to move to Abstract Factory.
In simple terms, the Abstract Factory is a factory that itself returns other factories. Think of it as a "factory of factories."
Real-Life Analogy:
- Factory Pattern: You walk into a Honda showroom and buy a car.
- Abstract Factory Pattern: You walk into a multi-brand showroom that offers Honda, Toyota, and other cars, and you choose a Honda.
UML Example:
In the diagram, the ICloudService
factory acts as a wrapper around DbServer
and AppServer
factories. Clients can create either type by calling CreateDbServer("azure")
or similar methods.
Example Code:
Imagine AbstractFactoryDesignPattern
as a client needing cloud servers.
using Contracts;
namespace AbstractFactoryDP.Services
{
public class AbstractFactoryDesignPattern : IDesignPattern
{
public object ExecuteDesignPattern()
{
ICloudServers cloudServers = new CloudServers();
var dbServer = cloudServers.CreateDbServer("azure");
dbServer.SetupDatabase();
return dbServer;
}
}
}
Key Components:
-
Abstract Factory (
ICloudServers
): Defines methods for creating related objects (e.g.,DbServer
,AppServer
). -
Concrete Factory (
CloudServers
): Implements the creation logic. -
Abstract Products (
DbServer
,AppServer
): Define interfaces for the concrete products. -
Concrete Products (
AzureDbServer
,AwsDbServer
, etc.): Implement these interfaces.
Complete Code Sample:
namespace AbstractFactoryDP.Services
{
public interface ICloudServers
{
public DbServer CreateDbServer(string provider);
public AppServer CreateAppServer(string provider);
}
public class CloudServers : ICloudServers
{
public DbServer CreateDbServer(string provider)
{
return provider.ToLower() switch
{
"azure" => new AzureDbServer(),
"aws" => new AwsDbServer(),
_ => new AzureDbServer()
};
}
public AppServer CreateAppServer(string provider)
{
return provider.ToLower() switch
{
"azure" => new AzureAppServer(),
"aws" => new AwsAppServer(),
_ => new AzureAppServer()
};
}
}
}
By leveraging Abstract Factory, you achieve a more scalable design for creating related products.
Final Thoughts
Both Factory and Abstract Factory patterns help decouple object creation logic, but their use cases differ:
- Use Factory Pattern when you need to create a single type of product.
- Use Abstract Factory Pattern when you need to create multiple related products.
If you have any questions or need further clarification, or if I miss something feel free to drop a comment. If this post helped you, don’t forget to share it with others!
Happy Coding! ✨
Top comments (0)