Design Patterns — Abstract Factory using .NET 3.1
In this article, we will create an example of using the Abstract Factory design using .NET 3.1.
When should I use the Abstract Factory Design Pattern?
Let’s try to answer this question in a simple way:
R: When we are in a context where several objects are highly
dependent on each other and we don’t want these
dependencies to be implemented in the main classes
of the project; If that is true, then we have the ideal scenario for
implementing this design pattern. Why? Just because the “Abstract Factory”
design pattern aims to place this dependency on classes that
represent the second or third level of abstraction.
Therefore, the main classes receives only what interests
them and the coupling is drastically reduced.
BOOM! JACKPOT!
Let’s start by giving an overview of the project layers for a better understanding of this definition:

Oooh is too much information, right?.. Let’s take it easy starting with the class Abstract Factory

This is our base class for creating device factories. As we can see, this class is abstract and has two method signatures:
“CreateDevice” : AbstractDevice

“CreateCharger”: AbstractCharger

These two abstract classes are from the “Abstract” layer and each of them represents the basic attributes of any device in our project.
The abstract class “AbstractDevice” in particular has the “Interact” method that receives the “AbstractCharger” class as a parameter. Basically, the purpose of this method is to start the device being used, as without a charger a device cannot work. Did you catch the idea? we will understand this more deeply in the next steps.
Let’s check out the “ConcreteClass” layer..
It’s easy to understand that this layer is responsible for implementing our “definitive” classes, that is, the classes that are at the highest level of abstraction.

In the “Charger” folder we create two types of chargers:
“ChargerS1":

“ChargerS2”:

Note that both classes inherit from the base class “AbstractCharger”, that is, these classes are at a higher level of abstraction. And it is precisely these classes that we have to avoid being coupled!
In the “Device” folder we create two types of devices:
“Cellphone”:

“Notebook”:

Note that the both classes inherit from the base class “AbstractDevice” and the only attributes they have that differ from each other are “WebcamModel” (Notebook) and “FrontalCameraModel” (Cellphone).
Now let’s see the “Factory” layer..

NotebookFactory class:

CellphoneFactory class:

Here, the same abstraction idea of the previous layers is applied, but in the context of “factories”, that is, the classes that will be responsible for creating some concrete product.
In this test scenario, we mocked the attributes of the classes just to initialize them through their constructors. That way, we can see the pattern being applied when we run the project and call this method.
Client Class:

The “Client” class has as attribute “Charger” and “Device” and these two attributes obviously receive the abstract class of your product, respecting the idea of the “Abstract Factory” design pattern. That is, we loose coupling due to the simple fact that main classes depend directly on abstractions and not implementations. ;)
The “Run” method calls the “Interact” method we created to do our responsibility delegation test. Definitely now everything makes more sense!
Program Class: In this class we will instantiate the “Client” class passing a concrete product as a parameter..

Now let’s see the magic!!
Output:

As expected, the values we assigned to each concrete product type in our “Mock” appeared on the screen output. Thus, the abstraction and delegation of responsibility that the “Abstract Factory” design pattern promises has been successfully implemented.
Obviously this was a very simple example of implementing this pattern in .NET. Thus, our idea was to guide the main concepts of this pattern so, based on that, other people can think about more complex implementations in different contexts. :)
Until next time, thanks!