Factory Method Design Pattern In C#

Introduction

Design patterns are all about reusable solutions to common problems in software designing that occur in real-world application development.

The 23 Gang of Four (GoF) patterns are generally considered the foundation for all other patterns. They are broadly categorized into three groups, i.e., Creational, Structural, and Behavioral. Factory method pattern falls under Creational Pattern of Gang of Four (GoF) Design Patterns.

Background

Before learning Factory Method Pattern, I just want to share a little about "Gang of Four (GoF)" to which the Factory Method 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 Factory Method design pattern:

Factory Method is a Design Pattern which defines an interface for creating an object, but lets the classes that implement the interface decide which class to instantiate. Factory Pattern lets a class postpone instantiation to sub-classes.

The factory pattern is used to replace class constructors, abstracting the process of object generation so that the type of the object instantiated can be determined at run-time.

In this article I have tried to cover the Concept of Factory Method design pattern and the way of implementing Factory Method design pattern.

Where to Use It?

It is tedious when the client needs to specify the class name while creating the objects. So, to resolve this problem, we can use Factory Method design pattern. It provides the client a simple way to create the object.

UML Class Diagram
Diagram
The classes and objects participating in the above UML class diagram are as follows:

  1. Product
    This defines the interface of objects the factory method creates
  1. ConcreteProduct
    This is a class which implements the Product interface.
  1. Creator
    This is an abstract class and declares the factory method, which returns an object of type Product.

    This may also define a default implementation of the factory method that returns a default ConcreteProduct object.

    This may call the factory method to create a Product object.

  1. ConcreteCreator
    This is a class which implements the Creator class and overrides the factory method to return an instance of a ConcreteProduct.

Now let’s understand this with a real world example

Assume you have three different cards which are considered here as classes MoneyBack, Titanium and Platinum, all of them implement abstract class CreditCard. You need to instantiate one of these classes, but you don't know which of them, it depends on the user. This is perfect scenario for the Factory Method design pattern.

 

Who is what?

The classes and objects participating in the above class diagram can be identified as follows:

  1. Product - CreditCard
  2. ConcreteProduct- MoneyBackCreditCard, TitaniumCreditCard, PlatinumCreditCard
  3. Creator- CardFactory
  4. ConcreteCreator- MoneyBackCardFactory, TitaniumCardFactory, PlatinumCardFactory

Here are the code blocks for each participant

  1. Product
    1. namespace FactoryMethodDesignPatternInCSharp  
    2. {  
    3.     /// <summary>  
    4.     /// The 'Product' Abstract Class  
    5.     /// </summary>  
    6.     abstract class CreditCard  
    7.     {  
    8.         public abstract string CardType { get; }  
    9.         public abstract int CreditLimit { get; set; }  
    10.         public abstract int AnnualCharge { get; set; }  
    11.     }     
    12. }  
  1. ConcreteProduct

    MoneyBackCreditCard
    1. using System;  
    2.   
    3. namespace FactoryMethodDesignPatternInCSharp  
    4. {  
    5.     /// <summary>  
    6.     /// A 'ConcreteProduct' class  
    7.     /// </summary>  
    8.     class MoneyBackCreditCard : CreditCard  
    9.     {  
    10.         private readonly string _cardType;  
    11.         private int _creditLimit;  
    12.         private int _annualCharge;  
    13.   
    14.         public MoneyBackCreditCard(int creditLimit, int annualCharge)  
    15.         {  
    16.             _cardType = "MoneyBack";  
    17.             _creditLimit = creditLimit;  
    18.             _annualCharge = annualCharge;  
    19.         }  
    20.   
    21.         public override string CardType  
    22.         {  
    23.             get { return _cardType; }  
    24.         }  
    25.   
    26.         public override int CreditLimit  
    27.         {  
    28.             get { return _creditLimit; }  
    29.             set { _creditLimit = value; }  
    30.         }  
    31.   
    32.         public override int AnnualCharge  
    33.         {  
    34.             get { return _annualCharge; }  
    35.             set { _annualCharge = value; }  
    36.         }  
    37.     }  
    38.  
    TitaniumCreditCard
    1. using System;  
    2.   
    3. namespace FactoryMethodDesignPatternInCSharp  
    4. {  
    5.     /// <summary>  
    6.     /// A 'ConcreteProduct' class  
    7.     /// </summary>  
    8.     class TitaniumCreditCard : CreditCard  
    9.     {  
    10.         private readonly string _cardType;  
    11.         private int _creditLimit;  
    12.         private int _annualCharge;  
    13.   
    14.         public TitaniumCreditCard(int creditLimit, int annualCharge)  
    15.         {  
    16.             _cardType = "Titanium";  
    17.             _creditLimit = creditLimit;  
    18.             _annualCharge = annualCharge;  
    19.         }  
    20.   
    21.         public override string CardType  
    22.         {  
    23.             get { return _cardType; }  
    24.         }  
    25.   
    26.         public override int CreditLimit  
    27.         {  
    28.             get { return _creditLimit; }  
    29.             set { _creditLimit = value; }  
    30.         }  
    31.   
    32.         public override int AnnualCharge  
    33.         {  
    34.             get { return _annualCharge; }  
    35.             set { _annualCharge = value; }  
    36.         }      
    37.     }  
    38. }  
    PlatinumCreditCard
    1. using System;  
    2.   
    3. namespace FactoryMethodDesignPatternInCSharp  
    4. {  
    5.     /// <summary>  
    6.     /// A 'ConcreteProduct' class  
    7.     /// </summary>  
    8.     class PlatinumCreditCard : CreditCard  
    9.     {  
    10.         private readonly string _cardType;  
    11.         private int _creditLimit;  
    12.         private int _annualCharge;  
    13.   
    14.         public PlatinumCreditCard(int creditLimit, int annualCharge)  
    15.         {  
    16.             _cardType = "Platinum";  
    17.             _creditLimit = creditLimit;  
    18.             _annualCharge = annualCharge;  
    19.         }  
    20.   
    21.         public override string CardType  
    22.         {  
    23.             get { return _cardType; }  
    24.         }  
    25.   
    26.         public override int CreditLimit  
    27.         {  
    28.             get { return _creditLimit; }  
    29.             set { _creditLimit = value; }  
    30.         }  
    31.   
    32.         public override int AnnualCharge  
    33.         {  
    34.             get { return _annualCharge; }  
    35.             set { _annualCharge = value; }  
    36.         }  
    37.     }  
    38. }  
  1. Creator
    1. namespace FactoryMethodDesignPatternInCSharp  
    2. {  
    3.     /// <summary>  
    4.     /// The 'Creator' Abstract Class  
    5.     /// </summary>  
    6.     abstract class CardFactory  
    7.     {  
    8.         public abstract CreditCard GetCreditCard();  
    9.     }  
    10. }  
  1. ConcreteCreator

    MoneyBackFactory
    1. namespace FactoryMethodDesignPatternInCSharp  
    2. {  
    3.     /// <summary>  
    4.     /// A 'ConcreteCreator' class  
    5.     /// </summary>  
    6.     class MoneyBackFactory : CardFactory  
    7.     {  
    8.         private int _creditLimit;  
    9.         private int _annualCharge;  
    10.   
    11.         public MoneyBackFactory(int creditLimit, int annualCharge)  
    12.         {  
    13.             _creditLimit = creditLimit;  
    14.             _annualCharge = annualCharge;  
    15.         }  
    16.   
    17.         public override CreditCard GetCreditCard()  
    18.         {  
    19.             return new MoneyBackCreditCard(_creditLimit, _annualCharge);  
    20.         }  
    21.     }  
    22. }  

TitaniumFactory 

  1. namespace FactoryMethodDesignPatternInCSharp      
  2. {      
  3.     class TitaniumFactory: CardFactory      
  4.     {      
  5.         private int _creditLimit;      
  6.         private int _annualCharge;      
  7.       
  8.         public TitaniumFactory(int creditLimit, int annualCharge)      
  9.         {      
  10.             _creditLimit = creditLimit;      
  11.             _annualCharge = annualCharge;      
  12.         }      
  13.       
  14.         public override CreditCard GetCreditCard()      
  15.         {      
  16.             return new TitaniumCreditCard(_creditLimit, _annualCharge);      
  17.         }      
  18.     }      
  19. }    
PlatinumFactory 
  1. namespace FactoryMethodDesignPatternInCSharp      
  2. {      
  3.     class PlatinumFactory: CardFactory      
  4.     {      
  5.         private int _creditLimit;      
  6.         private int _annualCharge;      
  7.       
  8.         public PlatinumFactory(int creditLimit, int annualCharge)      
  9.         {      
  10.             _creditLimit = creditLimit;      
  11.             _annualCharge = annualCharge;      
  12.         }      
  13.       
  14.         public override CreditCard GetCreditCard()      
  15.         {      
  16.             return new PlatinumCreditCard(_creditLimit, _annualCharge);      
  17.         }      
  18.     }      
  19. }   
Factory Pattern Client Demo 
  1. using System;  
  2.   
  3. namespace FactoryMethodDesignPatternInCSharp  
  4. {  
  5.     /// <summary>  
  6.     /// Factory Pattern Demo  
  7.     /// </summary>    
  8.     public class ClientApplication  
  9.     {  
  10.         static void Main()  
  11.         {  
  12.             CardFactory factory = null;  
  13.             Console.Write("Enter the card type you would like to visit: ");  
  14.             string car = Console.ReadLine();  
  15.   
  16.             switch (car.ToLower())  
  17.             {  
  18.                 case "moneyback":  
  19.                     factory = new MoneyBackFactory(50000, 0);  
  20.                     break;  
  21.                 case "titanium":  
  22.                     factory = new TitaniumFactory(100000, 500);  
  23.                     break;  
  24.                 case "platinum":  
  25.                     factory = new PlatinumFactory(500000, 1000);  
  26.                     break;  
  27.                 default:  
  28.                     break;  
  29.             }  
  30.   
  31.             CreditCard creditCard = factory.GetCreditCard();  
  32.             Console.WriteLine("\nYour card details are below : \n");  
  33.             Console.WriteLine("Card Type: {0}\nCredit Limit: {1}\nAnnual Charge: {2}",  
  34.                 creditCard.CardType, creditCard.CreditLimit, creditCard.AnnualCharge);  
  35.             Console.ReadKey();  
  36.         }  
  37.     }  
  38. }   

Output

Here, we are accepting input from the clients/users as to which class they want to instantiate.

Output

Enter the respective card type: (MoneyBack/Titanium/Platinum)

Output

Output

Summary

In this article, we have covered the basic concept of Factory Method 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!!!