Introduction
The Abstract Factory pattern is a creational design pattern that provides a way to create families of related or dependent objects without specifying their concrete classes. 1 It is useful when you want to decouple the creation of objects from their usage and when you want to have multiple variants of the same family of objects.
Example
Let’s say you want to create a simulation of different types of vehicles, such as cars, trucks, and motorcycles. You want to have different families of vehicles, such as family vehicles, sports vehicles, and luxury vehicles. Each family of vehicles has its concrete implementation of the car, truck, and motorcycle interfaces.
To implement the Abstract Factory pattern, you need to define the following components:
- An abstract product interface for each type of object, such as a Car, Truck, and Motorcycle.
- A concrete product class for each variant of each type of object, such as Mustang, PickupTruck, and SportBike for the family vehicles family.
- An abstract factory interface that declares methods for creating each type of object, such as VehicleFactory.
- A concrete factory class for each family of objects that implements the abstract factory interface and returns the appropriate concrete products, such as FamilyVehicleFactory.
The following code shows the implementation of these components in C#:
// Abstract product interfaces
public interface Car
{
void Drive();
}
public interface Truck
{
void Drive();
}
public interface Motorcycle
{
void Drive();
}
// Concrete product classes
public class Mustang : Car
{
public void Drive()
{
Console.WriteLine("Driving a Mustang");
}
}
public class PickupTruck : Truck
{
public void Drive()
{
Console.WriteLine("Driving a Pickup Truck");
}
}
public class SportBike : Motorcycle
{
public void Drive()
{
Console.WriteLine("Riding a Sport Bike");
}
}
// Abstract factory interface
public interface VehicleFactory
{
Car CreateCar();
Truck CreateTruck();
Motorcycle CreateMotorcycle();
}
// Concrete factory classes
public class FamilyVehicleFactory : VehicleFactory
{
public Car CreateCar()
{
return new Mustang();
}
public Truck CreateTruck()
{
return new PickupTruck();
}
public Motorcycle CreateMotorcycle()
{
return new SportBike();
}
}
To use the Abstract Factory pattern, you need to create a client class that takes an abstract factory as a parameter and uses its methods to create and use the objects. The client class does not know which concrete products it receives from the factory, as it only uses the abstract product interfaces. This way, you can change the factory at runtime and get different variants of the same family of objects.
The following code shows an example of a client class in C#:
public class Client
{
private VehicleFactory _vehicleFactory;
public Client(VehicleFactory vehicleFactory)
{
_vehicleFactory = vehicleFactory;
}
public void CreateVehicles()
{
Car car = _vehicleFactory.CreateCar();
Truck truck = _vehicleFactory.CreateTruck();
Motorcycle motorcycle = _vehicleFactory.CreateMotorcycle();
car.Drive();
truck.Drive();
motorcycle.Drive();
}
}
To test the Abstract Factory pattern, you can create different concrete factories and pass them to the client class. The following code shows an example of how to do this in C#:
class Program
{
static void Main(string[] args)
{
// Create a family vehicle factory
VehicleFactory familyVehicleFactory = new FamilyVehicleFactory();
// Create a client with the family vehicle factory
Client client = new Client(familyVehicleFactory);
// Create and use the family vehicles
client.CreateVehicles();
// Output:
// Driving a Mustang
// Driving a Pickup Truck
// Riding a Sport Bike
// Create another concrete factory here and pass it to the client to get different variants of the same family of objects
}
}
Benefits and Drawbacks
The Abstract Factory pattern has the following benefits:
- It promotes loose coupling by hiding the details of object creation from the client.
- It supports the open/closed principle by allowing new variants of objects to be added without changing the existing code.
- It supports the single responsibility principle by separating the creation of objects from their usage.
The Abstract Factory pattern has the following drawbacks:
- It may introduce unnecessary complexity and extra work in the initial writing of code.
- It may result in a large number of classes and interfaces, which can make the code harder to understand and maintain.
- It may require changes in the abstract factory interface and all its subclasses if new types of objects are added to the family.
Top comments (0)