NashTech Blog

Introduction to Factory Pattern in ASP.NET Core

Table of Contents
city, street, architecture-4667143.jpg

What is a Simple Factory Pattern?

The Simple Factory Pattern is a creational design pattern in object-oriented programming that provides a way to create objects without exposing the instantiation logic to the client. It involves a single factory class responsible for creating instances of different classes based on a specified input parameter. The client requests the creation of an object from the factory by providing parameters, and the factory decides which class to instantiate and returns the created object. This pattern promotes encapsulation by centralising object creation logic within the factory class, making it easier to manage and modify the instantiation process without affecting the client code.

Implementation: Simple Factory Pattern

 To understand the Simple Factory Pattern practically, we will take an example of a interface that defines the behaviour of a duck. All duck quacks, but different ducks quack in different ways. So we can create multiple concrete implementations using the interface.

 IDuck.cs

interface IDuck
{
    void Quack();
}

The concrete implementation of the above interface is as follows:

 DomesticDuck.cs

class DomesticDuck : IDuck
{
    public void Quack()
    {
         Console.WriteLine("Domestic duck quack");
    }
}

MallardDuck.cs

class MallardDuck : IDuck
{
   public void Quack()
    {
         Console.WriteLine("Mallard duck quack");
    }
}

RubberDuck.cs

class RubberDuck : IDuck
{
    public void Quack()
    {
         Console.WriteLine("Rubber duck quack");
    }
}

When implementing the Simple Factory Pattern, we need to create a class responsible for providing instances of objects based on requests. Let’s create a class named “DuckFactory” that implements an interface called “IDuckFactory”. This interface should include a method named “CreateDuck(DuckType type)”, which accepts an enum called “DuckType” and returns the corresponding instance of a Duck

IDuckFactory.cs

interface IDuckFactory
{
    IDuck CreateDuck(DuckType type);
}

DuckFactory.cs

class DuckFactory : IDuckFactory
{
    public IDuck CreateDuck(DuckType type)
    {
         switch (type)
         {
             case DuckType.DomesticDuck:
                 return new DomesticDuck();
             case DuckType.MallardDuck:
                 return new MallardDuck();
             case DuckType.RubberDuck:
                 return new RubberDuck();
             default:
                 return new DomesticDuck();
         }
    }
}

Code Explaination

This code is structured to facilitate the creation of various types of ducks using the Simple Factory design pattern in C#. It begins with the definition of an interface called IDuck, which outlines a method named Quack(). This interface serves as a blueprint for different types of ducks to follow.

Following the interface, concrete implementations for different types of ducks are provided: DomesticDuck, MallardDuck, and RubberDuck. Each of these classes implements the IDuck interface and provides its own unique implementation for the Quack() method, reflecting the distinct quacking behaviour of each duck type.

Moreover, to manage the creation of duck instances, an interface named IDuckFactory is introduced. This interface declares a method CreateDuck(DuckType type), which is responsible for creating instances of IDuck.

Subsequently, the actual factory implementation is presented in the DuckFactory class. This class implements the IDuckFactory interface and provides the logic for creating duck objects based on the specified DuckType. In the CreateDuck() method of the DuckFactory class, we use a switch statement to determine which type of duck to create based on the provided DuckType parameter. Depending on the type specified, the method creates and returns an instance of the corresponding duck class (DomesticDuck, MallardDuck, or RubberDuck).

In scenarios where an unknown or unsupported duck type is provided, the factory defaults to creating a DomesticDuck instance. Consequently, this ensures that the factory method remains robust and can handle unexpected input gracefully.

class Program
{
    static void Main(string[] args)
    {
         IDuckFactory simpleFactory = new DuckFactory();
         IDuck duck = simpleFactory.CreateDuck(DuckType.DomesticDuck);
         duck.Quack();
         Console.ReadLine();
    }
}

What is the Factory Method Pattern?

The Factory Method Pattern is a creational design pattern in object-oriented programming that defines an interface for creating objects, yet allows subclasses to alter the type of objects that will be created. Moreover, it provides a way to delegate the instantiation logic to subclasses, enabling them to decide which class to instantiate based on specific requirements or conditions. This pattern abstracts the instantiation process, thereby allowing the client code to work with objects through a common interface without being aware of the concrete classes being created. Consequently, this promotes flexibility and extensibility by enabling the addition of new subclasses without modifying existing client code.

“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses”

Implementation: Factory Method Pattern

Lets start with same code. We will use same interface called IDuck which were having one method as shown below.

interface IDuck
{
    void Quack();
}

These are the three concrete implementations which define the functionality of the function Quack().

class DomesticDuck : IDuck
{
    public void Quack()
    {
         Console.WriteLine("Domestic duck quack");
    }
}
class MallardDuck : IDuck
{
    public void Quack()
    {
         Console.WriteLine("Mallard duck quack");
    }
}
class RubberDuck : IDuck
{
     public void Quack()
    {
         Console.WriteLine("Rubber duck quack");
    }
}

As per the definition “Define an interface for creating an object…” Let’s proceed to establish the interface containing a method for producing fans. The implementation of this method in subclasses will involve the logic for generating specific fan instances.

interface IDuckFactory
{
    IDuck CreateDuck();
}

Continuing with the definition: “…let subclasses decide which class to instantiate…” Now, we’ll develop subclasses responsible for determining the specific class to use for creating an instance.”

To produce three types of objects—DomesticDuck, MallardDuck, and RubberDuck—we’ll require three distinct factories or subclasses of IFanFactory. Each of these factories will adhere to the IDuckFactory interface.

class DomesticDuckFactory : IDuckFactory
{
    public IDuck CreateDuck()
    {
         return new DomesticDuck();
    }
}
class MallardDuckFactory : IDuckFactory
{
    public IDuck CreateDuck()
    {
         return new MallardDuck();
    }
}
class RubberDuckFactory : IDuckFactory
{
    public IDuck CreateDuck()
    {
         return new RubberDuck();
    }
}

Continuing with the definition: “…Factory Method lets a class defer instantiation to subclasses.” Here, the method “IDuck CreateDuck();” is a Factory Method. Within the CreateDuck() method, which serves as a Factory Method, in concrete factories (such as DomesticDuckFactory, etc.), we specify the exact class to be instantiated for creating a Duck object. Therefore, IDuckFactory defers the decision-making process regarding the concrete class to its subclasses, namely DomesticDuckFactory, MallardDuckFactory, and RubberDuckFactory.

class Program
{
    static void Main(string[] args)
    {
         IDuckFactory duckFactory = new MallardDuckFactory();
         IDuck duck = duckFactory.CreateDuck();
          duck.Quack();
    }
}

What is Abstract Factory Pattern?

The Abstract Factory Pattern is a creational design pattern in object-oriented programming that provides an interface for creating families of related or dependent objects without specifying their concrete classes. Moreover, it is based on the concept of factories producing families of related objects. In this pattern, there is an abstract factory interface that declares a set of methods for creating each type of object in the family. Subsequently, concrete implementations of the abstract factory interface then provide specific implementations for creating objects of each type. As a result, this pattern enables the client code to work with a family of objects without worrying about the specific classes involved, promoting flexibility, and facilitating easy switching between different families of related objects.

“Provide an interface for creating families of related or dependent objects without specifying their concrete classes.”

Main Component/Participants of Abstract Factory Pattern

  • AbstractFactory (IElectricalFactory): An interface for creating families of related objects without specifying their concrete classes.
  • ConcreteFactory (IndianElectricalFactory, AmericanElectricalFactory): A class that implements the AbstractFactory interface to produce a specific family of related objects.
  • AbstractProduct (ILight, IAirCon): An interface declaring a set of methods that concrete products must implement.
  • ConcreteProduct (IndianLight, IndianAirCon, AmericanLight, AmericanAirCon) : A class that implements the AbstractProduct interface, defining the specific behaviour of a product in a product family.

Implementation: Abstract Factory Pattern

Here’s a simple guide to putting the scenario into action:

Start by making two interfaces named IFan and ITubelight.

interface ILight
{
     void LightOn();
}
interface IAirCon
{
     void AirConOn();
}

Let’s create two specific classes as described below by using the ILight and IAirCon interfaces. We’ll make sure that the interfaces are implemented according to the standards set for electrical equipment in India.

class IndianLight : ILight
{
    public void LightOn()
    {
         Console.WriteLine("Indian Light On");
    }
    }
class IndianAirCon : IAirCon
{
    public void AirConOn()
    {
         Console.WriteLine("Indian AC On");
    }
}

Let’s define an interface called IElectricalFactory. This interface serves as the actual Abstract Factory, responsible for creating groups of related objects.

interface IElectricalFactory
{
     ILight GetLight();
     IAirCon GetAirCon();
}

Next, we’ll create a class called IndianElecticalFactory, which inherits from the IElectricalFactory interface. This class will implement two methods: GetLight, which returns an object of the IndianLight class since the IndianLight class implements the ILight interface, and, additionally, GetAirCon, which returns an object of the IndianAirCon class.

class IndianElectricalFactory : IElectricalFactory
{
    public ILight GetLight()
    {
         return new IndianLight();
    }
    public IAirCon GetAirCon()
    {
         return new IndianAirCon();
    }
}

The IndianElecticalFactory class is now set up to produce IndianLight and IndianAirCon. Let’s explore how clients can go about creating them.

static void Main(string[] args)
{
    IElectricalFactory electricalFactory = new IndianElectricalFactory();
    ILight light = electricalFactory.GetLight();
    light.LightOn();
    Console.ReadKey();
}

Based on the previous section, the company plans to establish a new electrical company in the US, named AmericanElectricalFactory. Within the same application, we will introduce two new classes: AmericanLight and AmericanAirCon. These classes will implement the necessary interfaces, ILight and IAirCon, adhering to the electrical equipment standards in the US.

class AmericanLight : ILight
{
    public void LightOn()
    {
         Console.WriteLine("American Light On");
    }
}
class AmericanAirCon : IAirCon
{
    public void AirConOn()
    {
         Console.WriteLine("American AC On");
    }
}

To wrap up, let’s create the AmericanElectricalFactory class, which will also inherit from the IElectricalFactory interface.

class AmericanElectricalFactory : IElectricalFactory
{
    public ILight GetLight()
    {
         return new AmericanLight();
    }
    public IAirCon GetAirCon()
    {
         return new AmericanAirCon();
    }
}

If a client wishes to acquire AmericanElectrical equipment, they can easily do so by making just one adjustment to their code, as demonstrated below:

IElectricalFactory americanElectricalFactory = new AmericanElectricalFactory();

Conclusion

In conclusion, understanding the principles and distinctions among the Simple Factory, Factory Method, and Abstract Factory patterns is crucial for building robust and scalable applications in ASP.NET Core. Each pattern offers unique advantages and is tailored to specific design requirements. The Simple Factory pattern provides a straightforward approach to object creation, ideal for managing object instantiation in a single class. On the other hand, the Factory Method pattern introduces flexibility by allowing subclasses to alter the instantiation process, enabling the creation of related objects without tightly coupling the client code to their concrete classes. Moreover, the Abstract Factory pattern extends this flexibility further by defining families of related objects, promoting the creation of cohesive object systems while remaining independent of their concrete implementations.

Picture of Vipul Kumar

Vipul Kumar

Leave a Comment

Suggested Article

Discover more from NashTech Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading