CreationalC#verifiedVerified
Prototype Pattern in C#
Creates new objects by cloning an existing instance, avoiding the cost of building from scratch.
How to Implement the Prototype Pattern in C#
1Step 1: Define a cloneable prototype interface
public interface IPrototype<T>
{
T Clone();
}2Step 2: Concrete prototype with deep copy
public class Shape(string type, int x, int y, string color)
: IPrototype<Shape>
{
public string Type => type;
public int X => x;
public int Y => y;
public string Color => color;
public Shape Clone() => new(type, x, y, color);
public override string ToString() =>
$"{Type} at ({X},{Y}) color={Color}";
}3Step 3: Registry of pre-configured prototypes
public class ShapeRegistry
{
private readonly Dictionary<string, Shape> _prototypes = [];
public void Register(string key, Shape shape) =>
_prototypes[key] = shape;
public Shape Create(string key) =>
_prototypes.TryGetValue(key, out var proto)
? proto.Clone()
: throw new KeyNotFoundException($"No prototype: {key}");
}
// Usage:
// var registry = new ShapeRegistry();
// registry.Register("red-circle", new Shape("Circle", 0, 0, "Red"));
// var clone = registry.Create("red-circle");using System.Text.Json;
// [step] Deep-cloneable prototype interface with generic constraint
public interface IDeepCloneable<out T>
{
T DeepClone();
}
// [step] Complex document prototype with nested objects
public sealed class DocumentTemplate : IDeepCloneable<DocumentTemplate>
{
public required string Title { get; set; }
public required string Author { get; set; }
public List<Section> Sections { get; set; } = [];
public Dictionary<string, string> Metadata { get; set; } = [];
public DateTime CreatedAt { get; init; } = DateTime.UtcNow;
// [step] Deep clone via serialization for complex object graphs
public DocumentTemplate DeepClone()
{
var json = JsonSerializer.Serialize(this);
return JsonSerializer.Deserialize<DocumentTemplate>(json)
?? throw new InvalidOperationException("Clone failed");
}
}
public class Section
{
public required string Heading { get; set; }
public string Content { get; set; } = "";
public List<Section> SubSections { get; set; } = [];
}
// [step] Thread-safe prototype registry with factory methods
public sealed class PrototypeRegistry<T> where T : IDeepCloneable<T>
{
private readonly Dictionary<string, T> _prototypes = [];
private readonly ReaderWriterLockSlim _lock = new();
public void Register(string key, T prototype)
{
_lock.EnterWriteLock();
try { _prototypes[key] = prototype; }
finally { _lock.ExitWriteLock(); }
}
public T Create(string key)
{
_lock.EnterReadLock();
try
{
return _prototypes.TryGetValue(key, out var proto)
? proto.DeepClone()
: throw new KeyNotFoundException(
$"No prototype registered for '{key}'");
}
finally { _lock.ExitReadLock(); }
}
public bool TryCreate(string key, out T? result)
{
_lock.EnterReadLock();
try
{
if (_prototypes.TryGetValue(key, out var proto))
{
result = proto.DeepClone();
return true;
}
result = default;
return false;
}
finally { _lock.ExitReadLock(); }
}
public IReadOnlyList<string> ListKeys()
{
_lock.EnterReadLock();
try { return _prototypes.Keys.ToList().AsReadOnly(); }
finally { _lock.ExitReadLock(); }
}
}Prototype Pattern Architecture
hourglass_empty
Rendering diagram...
lightbulb
Prototype Pattern in the Real World
“Think of a cell dividing through mitosis. Instead of building a new cell from raw amino acids, the existing cell duplicates itself — copying its DNA, organelles, and membrane. The result is a fully functional copy produced far faster than assembling one molecule at a time.”