Objective ๐ฏ
Allow to create an object from cloning another object (Prototype), to hide the complexity of making new instances and to avoid costly operations.
Notes ๐
โข When 2 objects have the same reference it means that they are sharing the same space in memory and any change in one object will reflect in the other.
โข Normal Copy process preserves the reference of the original object including the objects inside it.
โข Shallow Copy process does not preserve the reference of the original object but keep the reference of the objects inside it.
โข Deep Copy process does not preserve the reference of the original object or the reference of the objects inside it.
Type โ
โBehavioral: Describes how objects interact/communicate between themselves.
โ๏ธCreational: Describes how to instantiate an object without large and complex.
โStructural: Describes how objects/classes are composed to form larger structures.
UML ๐
Participants ๐
โข Prototype:
- Declares an interface for cloning itself
โข ConcretePrototype:
- Implements an operation for cloning itself
โข Client:
- Creates new object by asking a prototype object to clone itself
Sample Code ๐ฎ
Structural Example ๐๏ธ
public static class PrototypeStructural
{
public static void Execute()
{
ConcretePrototype1 lConcretePrototype1 = new ConcretePrototype1("1");
ConcretePrototype1 lCloneConcretePrototype = (ConcretePrototype1)lConcretePrototype1.Clone();
Console.WriteLine($"Cloned {lConcretePrototype1.GetType().Name}");
ConcretePrototype2 lConcretePrototype2 = new ConcretePrototype2("2");
ConcretePrototype2 lCloneConcretePrototype2 = (ConcretePrototype2)lConcretePrototype2.Clone();
Console.WriteLine($"Cloned {lCloneConcretePrototype2.GetType().Name}");
}
}
public abstract class Prototype
{
public string _Id { get; set; }
public Prototype(string prId)
{
_Id = prId;
}
public abstract Prototype Clone();
}
public class ConcretePrototype1 : Prototype
{
public ConcretePrototype1(string prId)
: base(prId) { }
public override Prototype Clone()
{
return (Prototype)this.MemberwiseClone();
}
}
public class ConcretePrototype2 : Prototype
{
public ConcretePrototype2(string prId)
: base(prId) { }
public override Prototype Clone()
{
return (Prototype)this.MemberwiseClone();
}
}
Output
Real-world Example ๐ฅ
public static class PrototypePractical
{
public static void Execute()
{
ShapeHelper lShapeHelper = new ShapeHelper();
lShapeHelper.CreateShapes("Square", 2);
lShapeHelper.CreateShapes("Circle", 3);
lShapeHelper.CreateShapes("Triangle", 4);
Console.WriteLine($"\n\rCreated {lShapeHelper._Shapes.Count} objects in total");
}
}
public class ShapeHelper
{
public List<Shape> _Shapes = new List<Shape>();
public void CreateShapes(string prType, int prQuantity)
{
Shape lOriginalShape = null;
switch (prType)
{
case ("Circle"): lOriginalShape = new Circle("#1"); break;
case ("Square"): lOriginalShape = new Square("#1"); break;
case ("Triangle"): lOriginalShape = new Triangle("#1"); break;
default: break;
}
if (lOriginalShape != null)
{
Console.WriteLine($"โข Creating {prQuantity} {lOriginalShape.GetType().Name}s...");
Console.WriteLine($" Created object {lOriginalShape.GetType().Name} - Id: {lOriginalShape._Id}");
_Shapes.Add(lOriginalShape);
for (int i = 1; i < prQuantity; i++)
{
_Shapes.Add(lOriginalShape.Clone());
Console.WriteLine($" Clonned object {lOriginalShape.GetType().Name} - Id: {lOriginalShape._Id}");
}
}
}
}
public abstract class Shape
{
public string _Id { get; set; }
public string _Type { get; set; }
public Shape(string prId, string prType)
{
_Id = prId;
_Type = prType;
}
public virtual Shape Clone()
{
// To "Clone" an object can be done either by using Shallow Copy or Deep Copy approach
// In the below example Shallow Copy approach is used
return (Shape)this.MemberwiseClone();
}
}
public class Circle : Shape
{
public Circle(string prId)
: base(prId, "Circle") { }
}
public class Square : Shape
{
public Square(string prId)
: base(prId, "Square") { }
}
public class Triangle : Shape
{
public Triangle(string prId)
: base(prId, "Triangle") { }
}
Output