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
ICloneableinterface and declares theClonemethod. - Create concrete classes that inherit from the abstract class or implement the interface and override the
Clonemethod. You can use theMemberwiseClonemethod 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 Make, Model, Color and Price. We also have two concrete classes that inherit from Vehicle: Car 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
Post a Comment