Back to: Design Patterns in C# With Real-Time Examples
Abstract Factory Design Pattern in C# with Real-Time Example
In this article, I am going to discuss the Abstract Factory Design Pattern Real-Time Example in C#. Please read our previous article where we discussed the basic concept of Abstract Factory Design Patterns with Examples. As part of this article, we are going to discuss the following things.
- Real-Time Example to understand the Abstract Factory Pattern
- When to use Abstract Factory Design pattern.
- Differences between Abstract Factory and Factory Method Design Pattern
What is Abstract Factory Design Pattern?
The Abstract Factory Design Pattern belongs to the Creational Design Pattern Category and hence it is dealing with Object Creation and Initialization. As we already discussed in our previous article, the Abstract Factory Design Pattern provides an interface for creating families of related or dependent objects without specifying their concrete class names. We can also say that Abstract Factory is a super factory or we can say a factory of factories. That means it abstracts the client from knowing which factory would be returned from the abstract factory.
When to use Abstract Factory Design Pattern in Application Development?
We need to use Abstract Factory Design Pattern in C# when the client should not be aware of how objects are created and for which class object is created. This is helpful when an object needs to be created from a family of classes. We can apply the Abstract Factory Design Pattern in many kinds of projects. So, as a developer, we should know when to use this Abstract Factory Design Pattern in our Application Development. For example, if we have a group of objects with the same purpose, we could use the Abstract Factory Design Pattern to define an interface for creating new objects.
In general, we can use the Abstract Factory Design Pattern in the following scenarios:
- An application where the Client is independent or unaware of how the product classes are created and composed.
- An application where we have to define multiple families of products.
- An application where we have to define a group of classes that are designed to be used together.
How to implement the Abstract Factory Design Pattern in C#?
To Implement the Abstract Factory Design Pattern in C#, we need to use the following components.
- Abstract Product: These are going to be interfaces for creating abstract products. Here, we need to define the Operations a Product should have.
- Concrete Product: These are the classes that implement the Abstract Product interface.
- Abstract Factory: This is going to be an interface for operations that will create Abstract Product objects.
- Concrete Factory: These are the classes that implement the Abstract Factory interface and provide implementations for the interface methods. We can use these concrete classes to create concrete product objects.
- Client: This is a class that is going to use our Abstract Factory and Abstract Product interfaces to create a family of products.
For a better understanding of how these components are integrated together, please have a look at the following UML diagram of the Abstract Factory Design Pattern.
Abstract Factory Design Pattern Real-Time Example in C#:
Let us Implement Abstract Factory Design Pattern Real-Time Example in C# step by step with one Real-Time Example. We want to implement one application for showing the Course Details. Here, we want to show two types of courses i.e. Front End Courses and Back End Courses. Again, we also need to show how a student will learn these courses i.e. Sources. In this case, the source can be Online or Offline. Let us proceed and see how we can implement this application 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 Courses and Sources, so here we need to create two interfaces or abstract classes representing each abstract product type. Here, I am going to create two interfaces.
ICourse.cs
Create an interface with the name ICourse.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 Course product family should have a base interface. And in this case, all variants of Course products (Front-End and Back-End) must implement this ICourse interface. As you can see, we have created the following interface with three abstract methods and these methods are going to be implemented by the subclasses (FrontEndCourse and BackEndCourse).
namespace AbstractFactoryRealTimeExample { // The AbstractProductA interface // Each distinct product of the Course product family should have a base interface. // All variants of Course products must implement this ICourse interface. public interface ICourse { string GetCourseName(); int GetCourseFee(); string GetCourseDuration(); } }
ISource.cs
Create an interface with the name ISource.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 ISource product family should have a base interface. And in this case, all variants of the Source products (Online and Offline) must implement this ISource 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 (Online and Offline) of the ISource interface.
namespace AbstractFactoryRealTimeExample { // The AbstractProductB interface // Each distinct product of the Source product family should have a base interface. // All variants of Source products must implement this ISource interface. public interface ISource { string GetSourceName(); } }
Step 2: Creating Concrete Products
Now, we need to define the concrete product object or the actual product object which is going to be created by the corresponding concrete factory. The point that you need to remember is these concrete product classes must implement the Abstract Product Interface and provide implementation to the Interface methods. That means the concrete product class has to implement either ISource or ICourse interface in our example. So, let us create four concrete products i.e. FrontEndCourse, BackEndCourse, Online, and Offline as per our requirements.
FrontEndCourse.cs
Create a class file with the name FrontEndCourse.cs and then copy and paste the following code into it. The following FrontEndCourse Product Belongs to the Course product family. As you can see, it implements the ICourse interface and provides implementations for all three ICourse interface methods.
namespace AbstractFactoryRealTimeExample { // The ProductA1 class // Concrete Products are going to be created by corresponding Concrete Factories. // The following FrontEndCourse Product Belongs to the Course product family public class FrontEndCourse : ICourse { public string GetCourseName() { return "HTML, CSS, and Bootstrap"; } public string GetCourseDuration() { return "6 Months"; } public int GetCourseFee() { return 2000; } } }
BackEndCourse.cs
Create a class file with the name BackEndCourse.cs and then copy and paste the following code into it. The following BackEndCourse Product Belongs to the Course product family. As you can see, it implements the ICourse interface and provides implementations for all three ICourse interface methods.
namespace AbstractFactoryRealTimeExample { // The ProductB1 class // Concrete Products are going to be created by corresponding Concrete Factories. // The following BackEndCourse Product Belongs to the Course product family public class BackEndCourse : ICourse { public string GetCourseDuration() { return "6 Months"; } public int GetCourseFee() { return 1000; } public string GetCourseName() { return "C#, Java, and Python"; } } }
Online.cs
Create a class file with the name Online.cs and then copy and paste the following code into it. The following Online Product Belongs to the Source product family. As you can see, it implements the ISource interface and provides implementations for the GetSourceName method.
namespace AbstractFactoryRealTimeExample { // The ProductA2 class // Concrete Products are going to be created by corresponding Concrete Factories. // The following Online Product Belongs to the Source product family public class Online : ISource { public string GetSourceName() { return "Dot Net Tutorials Zoom Classes"; } } }
Offline.cs
Create a class file with the name Offline.cs and then copy and paste the following code into it. The following OfflineProduct Belongs to the Source product family. As you can see, it implements the ISource interface and provides implementations for the GetSourceName method.
namespace AbstractFactoryRealTimeExample { // The ProductB2 class // Concrete Products are going to be created by corresponding Concrete Factories. // The following Offline Product Belongs to the Source product family public class Offline : ISource { public string GetSourceName() { return "Dot Net Tutorials Class Room Training"; } } }
Step 3: Creating Abstract Factory
Now, we need to create an interface for operations that will create Abstract Product objects. In our example, it is going to be ISourceCourseFactory. So, create a class file with the name ISourceCourseFactory.cs and then copy and paste the following into it. As you can see this class contains two methods i.e. GetSource and GetCourse. The GetSource method is going to create different variants of Sources whereas the GetCourse method is going to create different variants of Courses. The point that you need to remember is here we are only declaring the methods and return type of these two methods are going to be abstract products i.e. ISource and ICourse. And hence from the child classes we can create different objects (objects of subclasses of ISource and ICourse).
namespace AbstractFactoryRealTimeExample { // 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 ISourceCourseFactory { //Abstract Product A ISource GetSource(); //Abstract Product B ICourse GetCourse(); } }
Step 4: Creating Concrete Factories
Now, we need to create concrete factory classes that implement abstract factory interfaces to create concrete product objects. In our example, we are going to create two Concrete Classes i.e. OnlineSourceCourseFactory and OfflineSourceCourseFactory.
OnlineSourceCourseFactory.cs
The OnlineSourceCourseFactory concrete class is going to create Online Source and Course Concrete Products. In our example, the Online Source and Course Concrete Products are Online and BackEndCourse. So, create a class file with the name OnlineSourceCourseFactory.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 (ICourse) and (ISource) while inside the method a concrete product (new Online and new BackEndCourse) is instantiated. So, the following Concrete Factory Produces Online Source and BackEndCourse Products which belong to the same OnlineSourceCourse Family.
namespace AbstractFactoryRealTimeExample { public class OnlineSourceCourseFactory : ISourceCourseFactory { public ISource GetSource() { return new Online(); } public ICourse GetCourse() { return new BackEndCourse(); } } }
OfflineSourceCourseFactory.cs
The OfflineSourceCourseFactory concrete class is going to create Offline Source and Course Concrete Products. In our example, the Offline Source and Course Concrete Products are Offline and FrontEndCourse. So, create a class file with the name OfflineSourceCourseFactory.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 (ICourse) and (ISource) while inside the method a concrete product (new Offline and new FrintEndCourse) is instantiated. So, the following Concrete Factory Produces Offline Source and FrontEndCourse Products which belong to the same OfflineSourceCourse Family.
namespace AbstractFactoryRealTimeExample { public class OfflineSourceCourseFactory : ISourceCourseFactory { public ISource GetSource() { return new Offline(); } public ICourse GetCourse() { return new FrontEndCourse(); } } }
Note: In our example, ISourceCourseFactory provides an interface to the client for creating families of related or dependent objects. Here we have two concrete implementations of that interface i.e. OnlineSourceCourseFactory and OfflineSourceCourseFactory classes. These two classes are manufacturing two different types of families of related objects i.e, Courses and Sources. Online and BackEndCourse classes belong to the OnlineSourceCourse family. On the other hand, Offline and FrondEndCourse classes belong to the OfflineSourceCourse 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 AbstractFactoryRealTimeExample { class Program { static void Main(string[] args) { // Fetch the Front End Course and Source Details // Creating OfflineSourceCourseFactory instance ISourceCourseFactory offlineSourceCourseFactory = new OfflineSourceCourseFactory(); //offlineSourceCourseFactory.GetCourse() will create and return FrondEndCourse object var course = offlineSourceCourseFactory.GetCourse(); Console.WriteLine("Front End Course and Source Details"); Console.WriteLine(course.GetCourseName()); Console.WriteLine(course.GetCourseFee()); Console.WriteLine(course.GetCourseDuration()); //offlineSourceCourseFactory.GetSource() will create and return Offline object var source = offlineSourceCourseFactory.GetSource(); Console.WriteLine(source.GetSourceName()); //Same steps for Online Course and Source Details Console.WriteLine("\n----------------------\n"); Console.WriteLine("Back End Course and Source Details"); ISourceCourseFactory onlineSourceCourseFactory = new OnlineSourceCourseFactory(); course = onlineSourceCourseFactory.GetCourse(); Console.WriteLine(course.GetCourseName()); Console.WriteLine(course.GetCourseFee()); Console.WriteLine(course.GetCourseDuration()); source = onlineSourceCourseFactory.GetSource(); Console.WriteLine(source.GetSourceName()); Console.ReadKey(); } } }
Output:
Abstract Factory Components in Our Example
- Client: Main Method of Program Class
- Abstract Product A: ICourse.cs
- Abstract Product B: ISource.cs
- ProductA1: FrontEndCourse.cs
- ProductB1: BackEndCourse.cs
- ProductA2: Online.cs
- ProductB2: Offline.cs
- Abstract Factory: ISourceCourseFactory.cs
- Concrete Factory1: OnlineSourceCourseFactory.cs
- Concrete Factory2: OfflineSourceCourseFactory.cs
Differences between Abstract Factory and Factory Method Design Pattern:
- Abstract Factory Design Pattern adds a layer of abstraction to the Factory Method Design Pattern
- The Abstract Factory design pattern implementation can have multiple factory methods
- Similar products of a factory implementation are grouped in the Abstract factory
- The Abstract Factory Pattern uses object composition to decouple applications from specific implementations
- The Factory Method Pattern uses inheritance to decouple applications from specific implementations
In the next article, I am going to discuss the Builder Design Pattern in C# with Examples. Here, in this article, I try to explain the Abstract Factory Design Pattern in C# with Real-Time 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 Abstract Factory Design Pattern Real-Time Example article.