Prototype Pattern in C#

Hello, fellow C# developers! In this post, I’m going to introduce you to the Prototype Pattern, one of the creational design patterns that can help you create new objects by cloning existing ones. Sounds cool, right? šŸ˜Ž

What is the Prototype Pattern?

According to the Gang of Four (GoF) definition, the Prototype Pattern “specifies the kind of objects to create using a prototypical instance, and create new objects by copying this prototype”.

In other words, this pattern allows you to avoid costly or complex object creation by reusing existing objects that have the same or similar properties. This way, you can save time and resources, and also avoid coupling your code to specific classes. šŸ‘

How to implement the Prototype Pattern in C#?

C# provides a built-in way to support the Prototype Pattern with the ICloneable interface and the MemberwiseClone method. The ICloneable interface defines a single method called Clone, which returns an object that is a copy of the current instance. The MemberwiseClone method creates a shallow copy of the current object by copying its fields. šŸ™Œ

To implement the Prototype Pattern in C#, you need to follow these steps:

  • Define an abstract class or an interface that implements the ICloneable interface and declares the Clone method.
  • Create concrete classes that inherit from the abstract class or implement the interface and override the Clone method. You can use the MemberwiseClone method to create a shallow copy of the current object, or you can implement your own logic to create a deep copy if needed.
  • Create a prototype manager class that stores a collection of prototype objects and provides a way to access them by a key or an identifier.
  • Use the prototype manager class to create new objects by cloning existing prototypes.

Example: Vehicle Prototype

Let’s see an example of how to use the Prototype Pattern in C# with vehicles. Suppose we have an abstract class called Vehicle that implements the ICloneable interface and has some properties such as MakeModelColor and Price. We also have two concrete classes that inherit from VehicleCar and Bike. Here is how we can define them:


// The abstract class that implements ICloneable
public abstract class Vehicle : ICloneable
{
    public string Make { get; set; }
    public string Model { get; set; }
    public string Color { get; set; }
    public decimal Price { get; set; }

    // The Clone method that returns a copy of the current object
    public abstract object Clone();
}

// The concrete class that inherits from Vehicle
public class Car : Vehicle
{
    // A property specific to Car
    public int Doors { get; set; }

    // The Clone method that creates a shallow copy using MemberwiseClone
    public override object Clone()
    {
        return this.MemberwiseClone();
    }
}

// Another concrete class that inherits from Vehicle
public class Bike : Vehicle
{
    // A property specific to Bike
    public string Type { get; set; }

    // The Clone method that creates a shallow copy using MemberwiseClone
    public override object Clone()
    {
        return this.MemberwiseClone();
    }
}


Next, we need to create a prototype manager class that stores and retrieves prototype objects. We can use a dictionary to store the prototypes by a key, and a method to get them by key. Here is how we can define it:


// The prototype manager class that stores and retrieves prototypes
public class VehicleManager
{
    // A dictionary to store prototypes by key
    private Dictionary<string, Vehicle> _vehicles = new Dictionary<string, Vehicle>();

    // A method to add a prototype by key
    public void AddVehicle(string key, Vehicle vehicle)
    {
        _vehicles.Add(key, vehicle);
    }

    // A method to get a prototype by key
    public Vehicle GetVehicle(string key)
    {
        return _vehicles[key];
    }
}


Finally, we can use the prototype manager class to create new objects by cloning existing prototypes. For example, we can create two prototypes: one for a car and one for a bike, and then clone them to create new objects with different properties. Here is how we can do it:


class Program
{
    static void Main(string[] args)
    {
        // Create a prototype manager instance
        VehicleManager vehicleManager = new VehicleManager();

        // Create a car prototype and add it to the manager
        Car carPrototype = new Car
        {
            Make = "Honda",
            Model = "Civic",
            Color = "Silver",
            Price = 20000,
            Doors = 4
        };
        vehicleManager.AddVehicle("Car", carPrototype);

        // Create a bike prototype and add it to the manager
        Bike bikePrototype = new Bike
        {
            Make = "Yamaha",
            Model = "FZ",
            Color = "Blue",
            Price = 5000,
            Type = "Sport"
        };
        vehicleManager.AddVehicle("Bike", bikePrototype);

        // Clone the car prototype and create a new car object
        Car car1 = (Car)vehicleManager.GetVehicle("Car").Clone();
        car1.Color = "Red"; // Change the color property

        // Clone the bike prototype and create a new bike object
        Bike bike1 = (Bike)vehicleManager.GetVehicle("Bike").Clone();
        bike1.Type = "Cruiser"; // Change the type property

        // Display the details of the original and cloned objects
        Console.WriteLine("Original Car: ");
        Console.WriteLine(carPrototype);
        Console.WriteLine("Cloned Car: ");
        Console.WriteLine(car1);
        Console.WriteLine("Original Bike: ");
        Console.WriteLine(bikePrototype);
        Console.WriteLine("Cloned Bike: ");
        Console.WriteLine(bike1);

        // Wait for user input
        Console.ReadKey();
    }
}


The output of the above program is:


Original Car: 
Make: Honda, Model: Civic, Color: Silver, Price: 20000, Doors: 4
Cloned Car: 
Make: Honda, Model: Civic, Color: Red, Price: 20000, Doors: 4
Original Bike: 
Make: Yamaha, Model: FZ, Color: Blue, Price: 5000, Type: Sport
Cloned Bike: 
Make: Yamaha, Model: FZ, Color: Blue, Price: 5000, Type: Cruiser


As you can see, we have created new objects by cloning existing prototypes and changing some properties as needed. This way, we have avoided creating new objects from scratch and also avoided coupling our code to specific classes. šŸŽ‰

Conclusion

The Prototype Pattern is a useful design pattern that lets us create new objects by cloning existing ones. This can help us save time and resources, and also avoid coupling our code to specific classes. C# provides a built-in way to support this pattern with the ICloneable interface and the MemberwiseClone method. However, we need to be careful when cloning objects that have reference type fields, as they may not be copied correctly by a shallow copy. In that case, we may need to implement a deep copy logic to clone the object and its references. 😊

I hope you enjoyed this post and learned something new about the Prototype Pattern in C#. If you have any questions or feedback, please feel free to leave a comment below. And don’t forget to share this post with your friends and colleagues who might be interested in learning more about design patterns in C#. 😁

References

C# Prototype Design Pattern - Dofactory

Prototype Design Pattern in C# with Examples - Dot Net Tutorials

Prototype Pattern in C# - DEV Community

Prototype Patterns in C# - C# Corner


You can find the code examples here: source code


See you next time!šŸ˜„

Comments

Popular posts from this blog

Which GOF patterns are good for C#?

Proxy pattern in C#

Bridge pattern in C#