C# Prototype Design Pattern

Learn how the C# Prototype Design Pattern enhances home security software development by enabling efficient object cloning. Discover implementation, benefits, and practical examples for security device management.

C# Prototype Design Pattern
Photo by Hal Gatewood / Unsplash

Introduction

The Prototype Pattern:

  • Creates new objects by copying existing instances (prototypes)
  • Avoids expensive initialization processes
  • Supports deep copying for complete object replication

Implementing Prototype

Deep Copy vs Shallow Copy

Type Behavior
Shallow Copies references to nested objects
Deep Creates new instances of nested objects

Implementation

  public interface IDeepCopyable<T> where T : new()
  {
    void CopyTo(T target);
    
    public T DeepCopy()
    {
      T t = new();
      CopyTo(t);
      return t;
    }
  }
  
  public record Address : IDeepCopyable<Address>
  {
    public string StreetName;
    public int HouseNumber;

    public Address(string streetName, int houseNumber)
    {
      StreetName = streetName;
      HouseNumber = houseNumber;
    }

    public Address() {}

    public override string ToString()
    {
      return $"{nameof(StreetName)}: {StreetName}, {nameof(HouseNumber)}: {HouseNumber}";
    }

    public void CopyTo(Address target)
    {
      target.StreetName = StreetName;
      target.HouseNumber = HouseNumber;
    }
  }



  public class Person : IDeepCopyable<Person>
  {
    public string[] Names;
    public Address Address;

    public Person()
    {
      
    }
    
    public Person(string[] names, Address address)
    {
      Names = names;
      Address = address;
    }

    public override string ToString()
    {
      return $"{nameof(Names)}: {string.Join(",", Names)}, {nameof(Address)}: {Address}";
    }

    public virtual void CopyTo(Person target)
    {
      target.Names = (string[]) Names.Clone();
      target.Address = Address.DeepCopy();
    }
  }

  public class Employee : Person, IDeepCopyable<Employee>
  {
    public int Salary;

    public void CopyTo(Employee target)
    {
      base.CopyTo(target);
      target.Salary = Salary;
    }

    public override string ToString()
    {
      return $"{base.ToString()}, {nameof(Salary)}: {Salary}";
    }
  }

Practical Application

// Create instance
var john = new Employee();
john.Names = new[] { "John", "Doe" };
john.Address = new Address { HouseNumber = 123, StreetName = "London Road" };
john.Salary = 321000;
// Clone for john
var copy = john.DeepCopy<Employee>();

copy.Names[1] = "Smith";
copy.Address.HouseNumber++;
copy.Salary = 123000;

WriteLine(john);
WriteLine(copy);

// Clone for new installation
var livingRoomConfig = indoorProfile.DeepClone();
livingRoomConfig.Settings["MotionSensitivity"] = "High";

Implementation Tips:

  1. Prefer deep cloning for complete configuration copies
  2. Combine with other patterns like Factory for enhanced flexibility
  3. Implement proper interface contracts (ICloneable or custom)

Subscribe to arash.ninja

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
[email protected]
Subscribe