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:
- Creational, focused to solve problems regarding objects creation mechanisms.
- Structural, creating a stable structure by design the relationship between entities.
- 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.
The Vehicle class that will be used as a base for the Car, Boat and Bus classes
- public abstract class Vehicle
- {
- internal int capacity;
- public abstract string GetData();
-
- public int GetCapacity()
- {
- return capacity;
- }
- public void AddPassengers(int passengers)
- {
- if (capacity < passengers)
- {
- throw new Exception(this.GetData() + " reached max capacity");
- }
- else
- capacity -= passengers;
- }
- }
Subclasses
Car, boat, and Bus classes that inherit from the vehicle class.
- class Boat : Vehicle
- {
-
- public override string GetData()
- {
- return "I am a boat!";
- }
- }
- class Bus : Vehicle
- {
-
- public override string GetData()
- {
- return "I am a Bus!";
- }
- }
- class Car : Vehicle
- {
- public override string GetData()
- {
- return "I am a car!";
- }
- }
Factory Superclass
The class that will be inherited from the Bus, Boat, and Car factory classes.
- public abstract class VehicleCreator
- {
- protected abstract Vehicle MakeVehicle();
-
- public Vehicle CreateVehicle()
- {
- return this.MakeVehicle();
- }
- }
Bus, Boat, and Car factory classes
The factory class responsible to create his own object.
- public class BoatCreator : VehicleCreator
- {
- protected override Vehicle MakeVehicle()
- {
- Vehicle vehicle = new Boat();
- vehicle.capacity = 150;
- return vehicle;
- }
- }
- public class CarCreator : VehicleCreator
- {
- protected override Vehicle MakeVehicle()
- {
- Vehicle vehicle = new Car();
- vehicle.capacity = 5;
- return vehicle;
- }
- }
- public class BusCreator : VehicleCreator
- {
- protected override Vehicle MakeVehicle()
- {
- Vehicle vehicle = new Bus();
- vehicle.capacity = 50;
- return vehicle;
- }
- }
The code running in the client, picking up the vehicle that he desires but without exposing the creation logic.
- class Program
- {
- static void Main(string[] args)
- {
- Vehicle vehicle;
- VehicleType vehicleType;
-
- Console.WriteLine("Hello! Which transport type would you prefer? We offer travels by Bus, Car and Boat.");
- var userInput = Console.ReadLine();
- if (Enum.TryParse(userInput, true, out vehicleType))
- {
- switch (vehicleType)
- {
- case VehicleType.Boat:
- vehicle = new BoatCreator().CreateVehicle();
- break;
- case VehicleType.Bus:
- vehicle = new BusCreator().CreateVehicle();
- break;
- case VehicleType.Car:
- vehicle = new CarCreator().CreateVehicle();
- break;
- default:
- vehicle = null;
- break;
- }
- Console.WriteLine(vehicle.GetData());
- Console.WriteLine("Vehicle capacity: " + vehicle.GetCapacity());
- }
- else
- {
- Console.WriteLine("Vehicle not found, try again.");
- }
- }
- public enum VehicleType
- {
- Bus,
- Car,
- Boat
- }
- }
Congratulations, you have successfully applied the Factory Method Design Pattern using C# with .NET Core.