Introduction
In my previous article, we covered Factory Method Design Pattern In C#. In this article, we will cover another design pattern in software design of C# application development, Abstract Factory.
Abstract Factory pattern also falls under Creational Pattern of Gang of Four (GoF) Design Patterns.
Background
Before learning Abstract Factory pattern, I just want to share a little about "Gang of Four (GoF)" to which the Abstract Factory pattern belongs.
Who are the Gang of Four?
The Gang of Four are the authors of the book, "Design Patterns: Elements of Reusable Object-Oriented Software". This important book describes various development techniques and pitfalls in addition to providing 23 object-oriented programming design patterns. The four authors are Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides.
Now, let's move on to the Abstract Factory design pattern.
In this article, I have tried to cover the concept of Abstract Factory design pattern and the ways of implementing Abstract Factory design pattern.
What is it?
An interface for creating families of related or dependent objects without specifying their concrete classes. We can say it is just an object maker which can create more than one type of object.
The object it produces is known to the client only by that object's interface, not by the object's actual concrete implementation.
When to use it?
We use it when we have a requirement to create a set of related objects, or dependent objects which must be used together as families of objects. Concrete classes should be decoupled from clients.
How does it differ from Factory Method?
First of all, both of them fall under Creational category and it means both will solve the problem relating to object creation. Factory Method and Abstract Factory design pattern are about creating objects.
Factory Method Design Pattern
Here, we define an interface which will expose a method which will create objects for us. Return type of that method is never a concrete type; rather, it will be some interface (or may be an abstract class).
- Creates object through inheritance
- Produce only one product
- Implements code in the abstract creator that makes use of the concrete type that sub class produces
Abstract Factory Design Pattern
Here, we define an interface which will create families of related or dependent objects. In simple words, interface will expose multiple methods each of which will create some object. Again, here method return types will be generic interfaces. All these objects will together become part of some important functionality.
- Creates object through composition
- Produce families of products
- Concrete factories implements factory method to create product
UML Class Diagram
The classes and objects participating in the above UML class diagram are as follow.
- AbstractFactory
This is an interface for operations which is used to create abstract product.
- ConcreteFactory
This is a class which implements the AbstractFactory interface operations to create concrete products.
- AbstractProduct
This declares an interface for a type of product object
- Product
This defines a product object to be created by the corresponding concrete factory also implements the AbstractProduct interface
- Client
This is a class which uses AbstractFactory and AbstractProduct interfaces to create a family of related objects.
Now, let’s understand this with a real world example.
The example here has an implementation of an Abstract Factory as an Interface IMobilePhone that has methods that can create a Smart Phone object and a Normal Phone object. The client codes against IMobilePhone and gets ISmartPhone and INormalPhone interfaces.
In case of "Nokia", it creates a family of Nokia objects (SmartPhone and NormalPhone) and in case of "Samsung", creates a family of Samsung objects (SmartPhone and NormalPhone).
The client doesn't care which object (Nokia SmartPhone and NormalPhone or Samsung SmartPhone and NormalPhone), IMobilePhone interface returns as it codes against ISmartPhone and INormalPhone interface.
Who is what?
The classes and objects participating in the above class diagram can be identified as shown below.
- AbstractFactory- IMobilePhone
- ConcreteFactory - Nokia, Samsung
- AbstractProduct- ISmartPhone, INormalPhone
- Product- NokiaPixel, Nokia1600, SamsungGalaxy, SamsungGuru
- Client- MobileClient
Here are the code blocks for each participant
- AbstractFactory
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- interface IMobilePhone
- {
- ISmartPhone GetSmartPhone();
- INormalPhone GetNormalPhone();
- }
- }
- ConcreteFactory
Nokia
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- class Nokia : IMobilePhone
- {
- public ISmartPhone GetSmartPhone()
- {
- return new NokiaPixel();
- }
-
- public INormalPhone GetNormalPhone()
- {
- return new Nokia1600();
- }
- }
- }
Samsung
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- class Samsung : IMobilePhone
- {
- public ISmartPhone GetSmartPhone()
- {
- return new SamsungGalaxy();
- }
-
- public INormalPhone GetNormalPhone()
- {
- return new SamsungGuru();
- }
- }
- }
- AbstractProduct
ISmartPhone
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- interface ISmartPhone
- {
- string GetModelDetails();
- }
- }
INormalPhone
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- interface INormalPhone
- {
- string GetModelDetails();
- }
- }
- Product
NokiaPixel
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- class NokiaPixel : ISmartPhone
- {
- public string GetModelDetails()
- {
- return "Model: Nokia Pixel\nRAM: 3GB\nCamera: 8MP\n";
- }
- }
- }
SamsungGalaxy
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- class SamsungGalaxy : ISmartPhone
- {
- public string GetModelDetails()
- {
- return "Model: Samsung Galaxy\nRAM: 2GB\nCamera: 13MP\n";
- }
- }
- }
Nokia1600
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- class Nokia1600 : INormalPhone
- {
- public string GetModelDetails()
- {
- return "Model: Nokia 1600\nRAM: NA\nCamera: NA\n";
- }
- }
- }
-
SamsungGuru
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- class SamsungGuru : INormalPhone
- {
- public string GetModelDetails()
- {
- return "Model: Samsung Guru\nRAM: NA\nCamera: NA\n";
- }
- }
- }
- Client
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- class MobileClient
- {
- ISmartPhone smartPhone;
- INormalPhone normalPhone;
-
- public Client(IMobilePhone factory)
- {
- smartPhone = factory.GetSmartPhone();
- normalPhone = factory.GetNormalPhone();
- }
-
- public string GetSmartPhoneModelDetails()
- {
- return smartPhone.GetModelDetails();
- }
-
- public string GetNormalPhoneModelDetails()
- {
- return normalPhone.GetModelDetails();
- }
- }
- }
Factory Pattern Client Demo
- using System;
-
- namespace AbstractFactoryDesignPatternInCSharp
- {
-
-
-
- class Program
- {
- static void Main()
- {
- IMobilePhone nokiaMobilePhone = new Nokia();
- MobileClient nokiaClient = new MobileClient(nokiaMobilePhone);
-
- Console.WriteLine("********* NOKIA **********");
- Console.WriteLine(nokiaClient.GetSmartPhoneModelDetails());
- Console.WriteLine(nokiaClient.GetNormalPhoneModelDetails());
-
- IMobilePhone samsungMobilePhone = new Samsung();
- MobileClient samsungClient = new MobileClient(samsungMobilePhone);
-
- Console.WriteLine("******* SAMSUNG **********");
- Console.WriteLine(samsungClient.GetSmartPhoneModelDetails());
- Console.WriteLine(samsungClient.GetNormalPhoneModelDetails());
-
- Console.ReadKey();
- }
- }
- }
Output
Summary
In this article, we have covered the basic concept of Abstract Factory design pattern and how to implement this in real world application development. I have attached the sample code for your reference.
I hope you enjoyed this article. Please share your valuable suggestions and feedback.
Happy Coding!!!