Back to: Design Patterns in C# With Real-Time Examples
Abstract Factory Design Pattern in C# with Examples
In this article, I am going to discuss the Abstract Factory Design Pattern in C# with Examples. Please read our previous article where we discussed the Factory Method Design Pattern in C# with an example. The Abstract Factory Design Pattern belongs to the creational design pattern category and is one of the most used design patterns in real-world applications. As part of this article, we are going to discuss the following things.
- What is Abstract Factory Design Pattern
- Example to understand the Abstract Factory Pattern
- Implementing Abstract Factory Design Pattern in C#
- When to use Abstract Factory Design Pattern.
What is Abstract Factory Design Pattern?
According to the Gang of Four Definition: The Abstract Factory Design Pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes.
In simple words, we can say that the Abstract Factory is a super factory that creates other factories. This Abstract Factory is also called the Factory of Factories. That means the Abstract Factory design pattern provides an interface for creating families of related or dependent products but leaves the actual object creation to the concrete factory classes. If this is not clear at the moment, then don’t worry, we will explain this with one Real-time Example.
Example to Understand Abstract Factory Design Pattern:
Let us understand the Abstract Factory Design Pattern with one Real-Time Example. First, we will implement the example, and then we will compare the Example with the Abstract Factory Design Pattern UML diagram so that you can easily understand the concept.
We want to implement one application for showing the Car and Bike details. Here, we want to show two types of bikes i.e. Regular Bikes and Sports Bikes as well as we want to show the details of two types of cars i.e. Regular cars and Sports cars. The point that you need to remember is a sports bike and a sports car belong to the same family called Sports. Similarly, Regular Bikes and Regular Cars also belong to the same family called Regular. With this kept in mind, let us proceed and see how we can implement this using the Abstract Factory Design Pattern in C#.
Step 1: Creating Abstract Products
Here, we need to declare interfaces for creating abstract products. As we are going to create two types of familiar products such as Bikes and Cars, so here we need to create two interfaces or abstract classes representing each abstract product type. Here, I am going to create two interfaces.
IBike.cs (AbstractProductA)
Create an interface with the name IBike.cs and then copy and paste the following code into it. This is going to be one of the Abstract Products. Each distinct product of the Bike product family should have a base interface. And in this case. All variants of Bike products (SportsBike and RegularBike) must implement this IBike interface. As you can see, we have created the following interface with one abstract method and that method is going to be implemented by the subclasses (SportsBike and RegularBike) of the IBike interface.
namespace AbstractFactoryDesignPattern { // The AbstractProductA interface // Each distinct product of the Bike product family should have a base interface. // All variants of Bike products must implement this IBike interface. public interface IBike { void GetDetails(); } }
ICar.cs (AbstractProductB)
Create an interface with the name ICar.cs and then copy and paste the following code into it. This is going to be our second Abstract Product. Each distinct product of the Car product family should have a base interface. And in this case. all variants of the Car products (SportsCar and RegularCar) must implement this ICar interface. As you can see, we have created the following interface with one abstract method and that method is going to be implemented by the subclasses of the ICar interface.
namespace AbstractFactoryDesignPattern { // The 'AbstractProductB' interface // Each distinct product of the Car product family should have a base interface. // All variants of the Car products must implement this ICar interface. public interface ICar { void GetDetails(); } }
Step 2: Creating Concrete Products
Here, we need to define the concrete product object which is going to be created by the corresponding concrete factory. How the concrete factory is going to create the product object, we will discuss later part of the article when we discuss the concrete factory component. The point that you need to remember is the concrete product classes must implement the Abstract Product Interface. That is the concrete product class has to implement either IBike or ICar interface in our example. So, let us create four concrete products i.e. RegularCar, SportsCar, RegularBike, and SportsBike as per our requirements.
RegularBike.cs (ProductA1)
Create a class file with the name RegularBike.cs and then copy and paste the following code into it. The following RegularBike Product Belongs to the Bike product family. As you can see, it implements the IBike interface and provides the implementation for the GetDetails method.
using System; namespace AbstractFactoryDesignPattern { // The ProductA1 class // Concrete Products are going to be created by corresponding Concrete Factories. // The following RegularBike Product Belongs to the Bike product family public class RegularBike : IBike { public void GetDetails() { Console.WriteLine("Fetching RegularBike Details.."); } } }
SportsBike.cs (ProductB1)
Create a class file with the name SportsBike.cs and then copy and paste the following code into it. The following SportsBike Product Belongs to the Bike product family. As you can see, it implements the IBike interface and provides implementations for the GetDetails method.
using System; namespace AbstractFactoryDesignPattern { // The ProductB1 class // Concrete Products are going to be created by corresponding Concrete Factories. // The following SportsBike Product Belongs to the Bike product family public class SportsBike : IBike { public void GetDetails() { Console.WriteLine("Fetching SportsBike Details.."); } } }
RegularCar.cs (ProductA2)
Create a class file with the name RegularCar.cs and then copy and paste the following code into it. The following RegularCar Product Belongs to the Car product family. As you can see, it implements the ICar interface and provides implementations for the GetDetails method.
using System; namespace AbstractFactoryDesignPattern { // The ProductA2 class // Concrete Products are going to be created by corresponding Concrete Factories. // The following RegularCar Product Belongs to the Car product family public class RegularCar : ICar { public void GetDetails() { Console.WriteLine("Fetching RegularCar Details.."); } } }
SportsCar.cs (ProductB2)
Create a class file with the name SportsCar.cs and then copy and paste the following code into it. The following SportsCar Product Belongs to the Car product family. As you can see, it implements the ICar interface and provides implementations for the GetDetails method.
using System; namespace AbstractFactoryDesignPattern { // The ProductB2 class // Concrete Products are going to be created by corresponding Concrete Factories. // The following SportsCar Product Belongs to the Car product family public class SportsCar : ICar { public void GetDetails() { Console.WriteLine("Fetching SportsCar Details.."); } } }
Step 3: Creating Abstract Factory
Here, we need to create an interface for operations that will create AbstractProduct objects. In our example, it is going to be IVehicleFactory. So, create a class file with the name IVehicleFactory.cs and then copy and paste the following into it. As you can see this class contains two methods. The CreateBike method is going to create different variants of Bikes whereas the CreateCar method is going to create different variants of Cars. The point that you need to remember is here we are only declaring the methods and returning the type of these two methods are going to be abstract products i.e. ICar and IBike. And hence from the child classes we can create different objects (objects of subclasses of ICar and IBike).
namespace AbstractFactoryDesignPattern { // The AbstractFactory interface // The Abstract Factory interface declares a set of methods that return different abstract products. // These products are called a family. // A family of products may have several variants public interface IVehicleFactory { //Abstract Product A IBike CreateBike(); //Abstract Product B ICar CreateCar(); } }
Note: The above abstract factory class is used to create a family of other factories. Let us proceed and create a such family of factories.
Step 4: Creating Concrete Factories
Here, we need to create concrete classes that implement the operations to create concrete product objects. These classes are going to implement the AbstractFactory interface and provide implementations for the two interface methods. In our example, we are going to create two Concrete Classes i.e. RegularVehicleFactory and SportsVehicleFactory.
RegularVehicleFactory.cs (ConcreteFactory1)
The RegularVehicleFactory concrete class is going to create Regular Vehicle Concrete Products. In our example, the Regular Vehicle Concrete Products are RegularBike and RegularCar. So, create a class file with the name RegularVehicleFactory.cs and then copy and paste the following code into it. If you notice, the signatures of the Concrete Factory’s methods return an abstract product (IBike) and (ICar) while inside the method a concrete product (new RegularBike and new RegularCar) is instantiated. So, the following Concrete Factory Produces Regular Bike and Regular Car Products which belong to the same Regular Family.
namespace AbstractFactoryDesignPattern { // The ConcreteFactory1 class // Concrete Factories produce a family of products that belong to a single variant. // The following Concrete Factory Produces Regular Bike and Car which are compatible // The signatures of the Concrete Factory's methods return an abstract product (IBike) and (ICar) // while inside the method a concrete product (new RegularBike and new RegularCar) is instantiated. public class RegularVehicleFactory : IVehicleFactory { public IBike CreateBike() { return new RegularBike(); } public ICar CreateCar() { return new RegularCar(); } } }
SportsVehicleFactory (ConcreteFactory2)
The SportsVehicleFactory concrete class is going to create Sports Vehicle Concrete Products. In our example, the Sports Vehicle Concrete Products are SportsBike and SportsCar. So, create a class file with the name SportsVehicleFactory.cs and then copy and paste the following code into it. If you notice, the signatures of the Concrete Factory’s methods return an abstract product (IBike) and (ICar) while inside the method a concrete product (new SportsBike and new SportsCar) is instantiated. So, the following Concrete Factory Produces Sports Bike and Sports Car Products which are belongs to the same Sports Family.
namespace AbstractFactoryDesignPattern { // The ConcreteFactory2 class // Concrete Factories produce a family of products that belong to a single variant. // The following Concrete Factory Produces Sports Bike and Sports Car which are compatible // The signatures of the Concrete Factory's methods return an abstract product (IBike) and (ICar) // while inside the method a concrete product (new SportsBike and new SportsCar) is instantiated. public class SportsVehicleFactory : IVehicleFactory { public IBike CreateBike() { return new SportsBike(); } public ICar CreateCar() { return new SportsCar(); } } }
Note: In our example, IVehicleFactory provides an interface to the client for creating families of related or dependent objects. Here we have two concrete implementations of that interface – RegularVehicleFactory and SportsVehicleFactory classes. These two classes are manufacturing two different types of families of related objects i.e, Bikes and Cars. RegularCar and RegularBike classes belong to the RegularVehicleFactory family. On the other hand, SportsCar and SportsBike classes belong to a SportsVehicleFactory family.
Step 5: Client
The Client is a class that uses AbstractFactory and AbstractProduct interfaces to create a family of related objects. In our example, it is going to be the Main method of the Program class. So, modify the Main method of the Program class as follows. The following example code is self-explained, so please go through the comment lines for a better understanding.
using System; namespace AbstractFactoryDesignPattern { //Client Code class Program { public static void Main() { // Fetch the Regular Bike and Car Details // Creating RegularVehicleFactory instance IVehicleFactory regularVehicleFactory = new RegularVehicleFactory(); //regularVehicleFactory.CreateBike() will create and return Regular Bike IBike regularBike = regularVehicleFactory.CreateBike(); regularBike.GetDetails(); //regularVehicleFactory.CreateCar() will create and return Regular Car ICar regularCar = regularVehicleFactory.CreateCar(); regularCar.GetDetails(); // Fetch the Sports Bike and Car Details Created // Creating SportsVehicleFactory instance IVehicleFactory sportsVehicleFactory = new SportsVehicleFactory(); //sportsVehicleFactory.CreateBike() will create and return Sports Bike IBike sportsBike = sportsVehicleFactory.CreateBike(); sportsBike.GetDetails(); //sportsVehicleFactory.CreateCar() will create and return Sports Car ICar sportsCar = sportsVehicleFactory.CreateCar(); sportsCar.GetDetails(); Console.ReadKey(); } } }
Output:
Abstract Factory Design Pattern UML (Class) Diagram:
Once we understand how to implement the Abstract Factory Design Pattern in C#, let us try to understand the UML (Unified Modeling Language) or Class diagram of the Abstract Factory Design Pattern. For a better understanding, please have a look at the following diagram which shows the different components of the Abstract Factory Method Design Pattern. Here, on the right-hand side, I am comparing the Abstract Factory Design Pattern component with our example, so that you can easily understand the different components of the Abstract Factory Design Pattern.
Let us understand each component of the Abstract Factory Design Pattern:
- Abstract Products: These are going to be interfaces for creating abstract products. Here, we need to define the Operations a Product should have. In our example, it is IBike.cs and ICar.cs interfaces.
- Concrete Products: These are the classes that implement the Abstract Product interface. In our example, RegularBike, SportsBike, RegularCar, and SportsCar classes are the Concrete Products.
- Abstract Factory: This is going to be an interface for operations that will create Abstract Product objects. In our example, it is going to be IVehicleFactory.
- Concrete Factory: These are the classes that implement the AbstractFactory interface and provide implementations for the interface methods. In our example, RegularVehicleFactory and SportsVehicleFactory are the concrete factory classes.
- Client: It is the class that is going to use the Abstract Product and Abstract Factory to create a family of products. In our example, it is the Main method of the Program class.
Abstract Factory Components in Our Example
- Client: Main Method of Program Class
- Abstract Product A: IBike.cs
- Abstract Product B: ICar.cs
- ProductA1: RegularBike.cs
- ProductB1: SportsBike.cs
- ProductA2: RegularCar.cs
- ProductB2: SportsCar.cs
- Abstract Factory: IVehicleFactory.cs
- Concrete Factory1: RegularVehicleFactory.cs
- Concrete Factory2: SportsVehicleFactory.cs
Pointe to Remember:
- Abstract Factory Pattern provides an interface for creating families of related dependent objects without specifying their concrete classes.
- The Abstract Factory Pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes.
- The abstract factory design pattern is merely an extension of the factory method pattern or factory pattern, which allows you to create objects without being concerned about the actual class of the object being created.
- Abstract means hiding some information and factory means which produces the products and pattern means a design. So, the Abstract Factory Pattern is a software design pattern that provides a way to encapsulate a group of individual factories that have a common theme.
In the next article, I am going to discuss the Abstract Factory Design Pattern Real-Time Examples in C#. Here, in this article, I try to explain the Abstract Factory Design Pattern in C# with Examples. I hope this article will help you with your needs. I would like to have your feedback. Please post your feedback, question, or comments about this article.
Again below code violates the open closed principle.how cane we solve that?
if we added new animal type
namespace AbstractFactoryDesignPattern
{
public class LandAnimalFactory : AnimalFactory
{
public override Animal GetAnimal(string AnimalType)
{
if (AnimalType.Equals(“Dog”))
{
return new Dog();
}
else if (AnimalType.Equals(“Cat”))
{
return new Cat();
}
else if (AnimalType.Equals(“Lion”))
{
return new Lion();
}
else
return null;
}
}
}
How does that violate the open-closed principle? Cause you create a new class and override the method which is called extension and you don’t change the existing class.
Yes it is violating the OCP. As when a new land animal is introduced, the LandAnimalFactory has to modified, instead it should have a new class for it’s instantiation. As per the Factory Method pattern. sub class has the responsibility of instantiating its own instance.
The correct implementation should be to have a factory method for each animal which is responsible for initializing its own object. (e.g. CatFactory, DogFactory etc.)
Yes, I am bit confused as it is violating SRP principle? and could you please put some real enterprise example so that correlate .
I think you could have take the previous credit card example to explain this. Could you please explain the same with the credit card example so that it will be easy to understand it and see the differences between factory method and abstract factory.