Factory Method Design Pattern With .NET Core

Introduction

 
In Software Development, design patterns are used to solve common architectural problems when designing an application or system. They must be used carefully and in the right situations for the right reasons.
 
If correctly used, design patterns may save developers a lot of time because they offer simple algorithms in order to solve complex problems. But, if not correctly used, they can bring a huge boost of complexity to your project, increasing difficulty to solve the problem. It is crucial to understand design patterns and their behavior to use their biggest advantages.
 
Design patterns are organized into three main groups, as follows:
  1. Creational, focused to solve problems regarding objects creation mechanisms.
  2. Structural, creating a stable structure by design the relationship between entities.
  3. Behavioral, improving objects behavior applying patterns on how they should communicate.

Benefits of using Design Patterns

  • Increased maintainability, with standardized algorithms;
  • Easy to apply, solving complex problems with best practices' solutions;
  • More efficiency, needing to do more with less code.

Related Articles

 
Check my previous articles about design patterns with .NET Core: 

What is the Factory Method Design Pattern?

 
The factory method design pattern is a creational design pattern, very common, and used in many software development projects. It is very similar to the Factory Design Pattern but in the Factory Method Design Pattern, you specify which type of object that you would like to return.
 
The Factory Method Design Pattern deals with the problem when we need to expose an object creation to the client, without exposing this object creation logic to the client. So, instead of exposing the object, we expose the classes with public methods to create this object in order to the client to understand which object is being created but the client does not know what is being done in the background alongside the object creation, so you may apply different algorithms for each of those objects created.
 

Why use the Factory Method Design Pattern?

 
The main benefit of using the factory method design pattern is to provide a way to the client instance one specific object without calling the constructor of this object directly, having different algorithms for each of those objects created.
 
Saying that we have, among others, these benefits:
  • The client knows exactly which object will be created;
  • Each object factory may have his own algorithms to apply while creating the object;
  • One factory does not need to know the other;

Implementation Step by Step With .NET Core

 
Use Case
 
In this example, we are going to have a C# with a .NET Core Console Application responsible to select the vehicle according to the user preference. The factory method will hold the logic to specify the maximum capacity of each vehicle.

 
Superclass
 
The Vehicle class that will be used as a base for the Car, Boat and Bus classes 
  1. public abstract class Vehicle  
  2. {  
  3.     internal int capacity;  
  4.     public abstract string GetData();  
  5.   
  6.     public int GetCapacity()  
  7.     {  
  8.         return capacity;  
  9.     }  
  10.     public void AddPassengers(int passengers)  
  11.     {  
  12.         if (capacity < passengers)  
  13.         {  
  14.             throw new Exception(this.GetData() + " reached max capacity");  
  15.         }  
  16.         else  
  17.             capacity -= passengers;  
  18.     }  
  19. }  
Subclasses
 
Car, boat, and Bus classes that inherit from the vehicle class. 
  1. class Boat : Vehicle  
  2. {  
  3.   
  4.     public override string GetData()  
  5.     {  
  6.         return "I am a boat!";  
  7.     }  
  8. }  
  9. class Bus : Vehicle  
  10. {  
  11.   
  12.     public override string GetData()  
  13.     {  
  14.         return "I am a Bus!";  
  15.     }  
  16. }  
  17. class Car : Vehicle  
  18. {  
  19.     public override string GetData()  
  20.     {  
  21.         return "I am a car!";  
  22.     }  
  23. }  
Factory Superclass
 
The class that will be inherited from the Bus, Boat, and Car factory classes.
  1. public abstract class VehicleCreator  
  2. {  
  3.     protected abstract Vehicle MakeVehicle();  
  4.   
  5.     public Vehicle CreateVehicle()  
  6.     {  
  7.         return this.MakeVehicle();  
  8.     }  
  9. }  
Bus, Boat, and Car factory classes
 
The factory class responsible to create his own object. 
  1. public class BoatCreator : VehicleCreator  
  2. {  
  3.     protected override Vehicle MakeVehicle()  
  4.     {  
  5.         Vehicle vehicle = new Boat();  
  6.         vehicle.capacity = 150;  
  7.         return vehicle;  
  8.     }  
  9. }  
  10. public class CarCreator : VehicleCreator  
  11. {  
  12.     protected override Vehicle MakeVehicle()  
  13.     {  
  14.         Vehicle vehicle = new Car();  
  15.         vehicle.capacity = 5;  
  16.         return vehicle;  
  17.     }  
  18. }  
  19. public class BusCreator : VehicleCreator  
  20. {  
  21.     protected override Vehicle MakeVehicle()  
  22.     {  
  23.         Vehicle vehicle = new Bus();  
  24.         vehicle.capacity = 50;  
  25.         return vehicle;  
  26.     }  
  27. }  
Client code
 
The code running in the client, picking up the vehicle that he desires but without exposing the creation logic. 
  1. class Program  
  2. {  
  3.     static void Main(string[] args)  
  4.     {  
  5.         Vehicle vehicle;  
  6.         VehicleType vehicleType;  
  7.   
  8.         Console.WriteLine("Hello! Which transport type would you prefer? We offer travels by Bus, Car and Boat.");  
  9.         var userInput = Console.ReadLine();  
  10.         if (Enum.TryParse(userInput, trueout vehicleType))  
  11.         {  
  12.             switch (vehicleType)  
  13.             {  
  14.                 case VehicleType.Boat:  
  15.                     vehicle = new BoatCreator().CreateVehicle();  
  16.                     break;  
  17.                 case VehicleType.Bus:  
  18.                     vehicle = new BusCreator().CreateVehicle();  
  19.                     break;  
  20.                 case VehicleType.Car:  
  21.                     vehicle = new CarCreator().CreateVehicle();  
  22.                     break;  
  23.                 default:  
  24.                     vehicle = null;  
  25.                     break;  
  26.             }  
  27.             Console.WriteLine(vehicle.GetData());  
  28.             Console.WriteLine("Vehicle capacity: " + vehicle.GetCapacity());  
  29.         }  
  30.         else  
  31.         {  
  32.             Console.WriteLine("Vehicle not found, try again.");  
  33.         }  
  34.     }  
  35.     public enum VehicleType  
  36.     {  
  37.         Bus,  
  38.         Car,  
  39.         Boat  
  40.     }
  41. }  
Congratulations, you have successfully applied the Factory Method Design Pattern using C# with .NET Core.