Understanding the Prototype Pattern in C# with Practical Examples
Daniel Azevedo
Posted on October 4, 2024
Hi devs,
When working with large systems, especially in enterprise-level applications like payroll or HR systems, it can be beneficial to clone objects instead of creating new ones from scratch. This is where the Prototype Pattern comes in handy. In this post, I’ll walk you through what the Prototype Pattern is and how it can be applied in a C# payroll system, using both shallow copy and deep copy.
What is the Prototype Pattern?
The Prototype Pattern is a creational design pattern that allows us to clone objects, effectively copying their properties without needing to instantiate them from scratch. It’s useful in situations where object creation is resource-heavy or when we need to keep the state of the object being cloned.
Key Concepts: Shallow Copy vs. Deep Copy
- Shallow Copy: A shallow copy of an object duplicates only the top-level fields, meaning references within the object are copied by reference, not duplicated.
- Deep Copy: A deep copy duplicates the object and all objects it references, ensuring that the new instance is independent of the original.
Applying the Prototype Pattern in a Payroll System
Let’s use an example based on salary processing in a human resources (HR) application. In this case, each Employee
object has a Salary
object associated with it.
Step 1: Define the Prototype Interface
First, we define an interface that will allow us to clone objects.
public interface IPrototype<T>
{
T Clone();
}
This interface guarantees that any class implementing it will provide a method to clone objects.
Step 2: Implement the Employee
Class with Prototype
Here, we’ll create our Employee
class, which has properties like Name
and Salary
. We’ll implement both shallow and deep copy methods.
public class Employee : IPrototype<Employee>
{
public string Name { get; set; }
public Salary Salary { get; set; }
// Shallow copy
public Employee Clone()
{
return (Employee)this.MemberwiseClone();
}
// Deep copy
public Employee DeepClone()
{
Employee cloned = (Employee)this.MemberwiseClone();
cloned.Salary = new Salary { Amount = this.Salary.Amount };
return cloned;
}
}
public class Salary
{
public decimal Amount { get; set; }
}
Here:
-
Clone()
provides a shallow copy of theEmployee
, meaning theSalary
reference will still be shared between copies. -
DeepClone()
ensures that theSalary
object is also cloned, making it a deep copy.
Step 3: Example of Using Shallow and Deep Copies
Let’s see how the Prototype Pattern can be used in a payroll context:
class Program
{
static void Main()
{
// Original Employee
Employee emp1 = new Employee
{
Name = "John",
Salary = new Salary { Amount = 5000 }
};
Employee emp2 = emp1.Clone();
emp2.Name = "Jane";
emp2.Salary.Amount = 5500;
Employee emp3 = emp1.DeepClone();
emp3.Name = "Bob";
emp3.Salary.Amount = 6000;
Console.WriteLine($"emp1: {emp1.Name}, Salary: {emp1.Salary.Amount}");
Console.WriteLine($"emp2: {emp2.Name}, Salary: {emp2.Salary.Amount}");
Console.WriteLine($"emp3: {emp3.Name}, Salary: {emp3.Salary.Amount}");
}
}
Explanation:
- After performing a shallow copy with
emp2
, any changes toemp2.Salary.Amount
also affectemp1.Salary.Amount
, because both employees share the sameSalary
reference. - With deep copy using
emp3
, changes toemp3.Salary.Amount
do not affectemp1.Salary.Amount
, becauseemp3
has its own separateSalary
instance.
Why Use the Prototype Pattern?
This pattern can be especially useful in payroll systems or HR applications where object creation (e.g., creating multiple employees with similar data) can be repetitive and resource-intensive. Cloning can save time and reduce complexity.
Conclusion
The Prototype Pattern provides a flexible and efficient way to clone objects, allowing you to decide whether to perform a shallow or deep copy depending on your needs. In scenarios like salary processing or HR systems, this can reduce overhead and make code cleaner and more efficient.
Keep coding
Posted on October 4, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.