The second design pattern in Creational category is the Factory Pattern. Let's take a look at this pattern to see what it is and how to implement it in our program.
Note: Code can be downloaded at my Github
1. What is the Factory Design Pattern?
In real world applications, Factory Pattern is one of the most used design patterns. By using this pattern, objects are created without exposing the creation logic to the client by using a common interface.
Factory Design Pattern defines an interface for creating an object, but let subclasses decide which class to instantiate. The Factory method lets a class defer instantiation it uses to subclasses.
2. When to use the Factory Design Pattern?
The Factory Design Pattern is used when you have classes which don't know what exact sub-classes it has to create. It happens in real world application when the Product implementation tends to change over time but the Client needs to remain unchanged.
For example, you are working at a logistics company which uses trucks as main vehicles to ship goods. You, as a developer, may come up with below design when developing a logistics application for your company.
Create a Truck class:
public class Truck { public string Type { get; set; } public Truck() { Type = "Truck"; } public void Delivery() { Console.WriteLine($"{Type} is used for delivery."); } }
Then, you need to initiate an object from your Truck class and call delivery function:
class Program { static void Main(string[] args) { Truck truck = new Truck(); truck.Delivery(); } }
This design works fine but it can’t scale up. For example, if your company attracts more clients and many of them prefer air or sea shipping methods, you would need to modify the entire project code which is now coupled to the Truck class. Here, you need to add a new Ship class for sea shipping method and the Client's code need to be modified to initiate an object from the Ship class.
public class Ship { public string Type { get; set; } public Ship() { Type = "Ship"; } public void Delivery() { Console.WriteLine($"{Type} is used for delivery."); } } class Program { static void Main(string[] args) { Ship ship = new Ship(); ship.Delivery(); } }
So, we need to come up with a better design which the initiated objects are not coupled to the existing or new classes. The Factory Design Pattern can resolve this problem.
3. How to Implement Factory Design Pattern?
Look back at the definition of Factory Design Pattern, it says: "define an interface for creating objects". We can follow below step to implement the Factory Design Pattern in C# and .Net.
Step 1: Create a generic class
We should create an abstract Vehicle class and child classes for each type of vehicles. I also have an enum for VehicleType.
public enum VehicleType { Truck, Ship, Airplane } public abstract class Vehicle { public abstract string Type { get; set; } public abstract void Delivery(); }
Classes for each vehicle type are inherited from Vehicle abstract class:
public class TruckVehicle : Vehicle { public TruckVehicle() { Type = VehicleType.Truck.ToString(); } public override string Type { get; set; } public override void Delivery() { Console.WriteLine($"{Type} is used for delivery."); } } public class ShipVehicle : Vehicle { public ShipVehicle() { Type = VehicleType.Ship.ToString(); } public override string Type { get; set; } public override void Delivery() { Console.WriteLine($"{Type} is used for delivery."); } } public class AirplaneVehicle : Vehicle { public AirplaneVehicle() { Type = VehicleType.Airplane.ToString(); } public override string Type { get; set; } public override void Delivery() { Console.WriteLine($"{Type} is used for delivery."); } }
Step 2: Create a Factory class
We can now create a VehicleFactory class which will be used to create different vehicle types such as trucks, ships, or airplanes.
public interface IVehicleFactory { Vehicle NewTruck(); Vehicle NewShip(); Vehicle NewAirplane(); } public class VehicleFactory : IVehicleFactory { public Vehicle NewAirplane() { return new AirplaneVehicle(); } public Vehicle NewShip() { return new ShipVehicle(); } public Vehicle NewTruck() { return new TruckVehicle(); } }
Now, we can initiate different vehicle objects depending on the Client needs by using the Factory we just created.
class Program { static void Main(string[] args) { VehicleFactory vf = new VehicleFactory(); Vehicle truckVehicle = vf.NewTruck(); truckVehicle.Delivery(); Vehicle shipVehicle = vf.NewShip(); shipVehicle.Delivery(); Vehicle airplaneVehicle = vf.NewAirplane(); airplaneVehicle.Delivery(); } }
We can see that the VehicleFactory class is serving as an interface which is used to create objects for each vehicle type. The instantiation is not coupled to the child classes anymore. So, when we have a new type of shipping vehicle, we still can call the VehicleFactory to create an object of the new class.