Prototype – A fully initialized instance to be copied or cloned.
From Design Patterns – Introduction
Structure
Applicability
When the source code shouldn’t depend on the object’s class, you need to use this pattern to copy.
Reduce the number of the subclasses which only differ in initializing their respective objects.
Pros and Cons
PRONS
CONS
How to Implement
#1 Basic Sample
public class Demo
{
public int ID { get; set; } = 1;
public string Name { get; set; } = string.Empty;
public IdInfo IdInfo;
public Demo ShallowCopy()
{
return (Demo)this.MemberwiseClone();
}
public Demo DeepCopy()
{
Demo clone = (Demo)this.MemberwiseClone();
clone.IdInfo = new IdInfo(IdInfo.IdNumber);
clone.Name = String.Copy(Name);
return clone;
}
}
public class IdInfo
{
public Guid IdNumber;
public IdInfo(Guid _IdNumber) => IdNumber = _IdNumber;
}
class Program
{
static void Main(string[] args)
{
Demo p1 = new Demo
{
Name = "Jack",
IdInfo = new IdInfo(Guid.NewGuid())
};
// Perform a shallow copy of p1 and assign it to p2.
Demo p2 = p1.ShallowCopy();
// Make a deep copy of p1 and assign it to p3.
Demo p3 = p1.DeepCopy();
// Display values of p1, p2 and p3.
Console.WriteLine("Original values of p1, p2, p3:");
Console.WriteLine(" p1 instance values: ");
Console.WriteLine(" ID: {0}, Name: {1},GUID: {2}",
p1.ID, p1.Name, p1.IdInfo.IdNumber.ToString());
Console.WriteLine(" p2 instance values:");
Console.WriteLine(" ID: {0}, Name: {1},GUID: {2}",
p2.ID, p2.Name, p2.IdInfo.IdNumber.ToString());
Console.WriteLine(" p3 instance values:");
Console.WriteLine(" ID: {0}, Name: {1},GUID: {2}",
p3.ID, p3.Name, p3.IdInfo.IdNumber.ToString());
p1.Name = "Frank";
p1.IdInfo.IdNumber = Guid.NewGuid();
Console.WriteLine("\nValues of p1, p2 and p3 after changes to p1:");
Console.WriteLine(" p1 instance values: ");
Console.WriteLine(" ID: {0}, Name: {1},GUID: {2}",
p1.ID, p1.Name, p1.IdInfo.IdNumber.ToString());
Console.WriteLine(" p2 instance values (reference values have changed):");
Console.WriteLine(" ID: {0}, Name: {1},GUID: {2}",
p2.ID, p2.Name, p2.IdInfo.IdNumber.ToString());
Console.WriteLine(" p3 instance values (everything was kept the same):");
Console.WriteLine(" ID: {0}, Name: {1},GUID: {2}",
p3.ID, p3.Name, p3.IdInfo.IdNumber.ToString());
Console.ReadKey();
}
} #2 Web Application Project
Step 1 Create the generic repository class mechanism for the prototype patterns. The interface class name sets “IPrototype.” The generic repository class name sets “PrototypeRepo.” One method that can affect operation is a GET method, which works to get a single data function. This method name sets “Prototype_GetById.”
The IPrototype class file source code shows below:
public interface IPrototype<T> where T : class
{
T Prototype_GetById(int id);
} The statement the variable of the IGenericTypeRepository class in the PrototypeRepo class. The Prototype_GetById method uses the IGenericTypeRepository variable to call the GetById method of GenericTypeRepository and return T.
The PrototypeRepo class file source code shows below:
public class PrototypeRepo<T> : IPrototype<T> where T : class
{
private IGenericTypeRepository<T> repo;
public PrototypeRepo(IGenericTypeRepository<T> _repo)
{
this.repo = _repo;
}
public T Prototype_GetById(int id) => repo.GetById(id).Result as T;
} Step 2 Create a new entity model class under the Core project for the prototype patterns to create. The new entity model class file name sets “PrototypeEntity.”
The PrototypeEntity class file source code shows below:
public class PrototypeEntity
{
public int ID { get; set; }
public string Name { get; set; }
public int? Age { get; set; }
public IdInfo IdInfo;
public PrototypeEntity ShallowCopy()
{
return (PrototypeEntity)this.MemberwiseClone();
}
public PrototypeEntity DeepCopy()
{
PrototypeEntity clone = (PrototypeEntity)this.MemberwiseClone();
clone.IdInfo = new IdInfo(IdInfo.IdNumber);
return clone;
}
}
public class IdInfo
{
public Guid IdNumber;
public IdInfo(Guid _IdNumber) => IdNumber = _IdNumber;
} Note: In the prototype class diagram UML picture, you can find an IdInfo class object in the PrototypeEntity class to statement. I short the code and write it in the same class file because I want the reader to read these elements easily.
Step 3 Create a controller file and view files under the web project. The controller file name sets “PrototypeController.” The view part creates the Index page.
Step 4 Call a single data by IPrototype class, then layout the result by ViewData method. After calling single information, the entity model object re-sets the object’s value, such as the new GUID, the name field, then puts the result to the Tuple object.
The Index page source code of the PrototypeController file shows below:
public IActionResult Index()
{
var PrototypeObj = repo.Prototype_GetById(1);
PrototypeEntity prototypeEntity = new PrototypeEntity()
{
ID = PrototypeObj.ID,
Name = PrototypeObj.Name,
Age = PrototypeObj.Age,
IdInfo = new IdInfo(Guid.NewGuid())
};
PrototypeEntity prototypeEntity2 = prototypeEntity.ShallowCopy();
PrototypeEntity prototypeEntity3 = prototypeEntity.DeepCopy();
Tuple<PrototypeEntity, PrototypeEntity, PrototypeEntity> Result_tuple =
new Tuple<PrototypeEntity, PrototypeEntity, PrototypeEntity>(prototypeEntity, prototypeEntity2, prototypeEntity3);
// Before
// prototypeEntity object
ViewData["Item1_ID"] = prototypeEntity.ID;
ViewData["Item1_Name"] = prototypeEntity.Name;
ViewData["Item1_Age"] = prototypeEntity.Age;
ViewData["Item1_Guid"] = prototypeEntity.IdInfo.IdNumber;
// prototypeEntity2 object
ViewData["Item2_ID"] = prototypeEntity2.ID;
ViewData["Item2_Name"] = prototypeEntity2.Name;
ViewData["Item2_Age"] = prototypeEntity2.Age;
ViewData["Item2_Guid"] = prototypeEntity2.IdInfo.IdNumber;
// prototypeEntity3 object
ViewData["Item3_ID"] = prototypeEntity3.ID;
ViewData["Item3_Name"] = prototypeEntity3.Name;
ViewData["Item3_Age"] = prototypeEntity3.Age;
ViewData["Item3_Guid"] = prototypeEntity3.IdInfo.IdNumber;
// After
prototypeEntity.Name = "After_Changed_Nmae";
prototypeEntity.IdInfo.IdNumber = Guid.NewGuid();
return View(Result_tuple);
}
Reference
What is the API gateway? An API gateway is an API management tool that sits…
The .NET 5 SDK is a kind of milestone in the .NET world. The .NET…
In object-oriented design, the dependency inversion principle is a specific methodology for loosely coupling software…
In the field of software engineering, the interface segregation principle (ISP) states that no code…
Subtype Requirement: Let be a property provable about objects of type T. Then should be true for objects of type S where S is…
In object-oriented programming, the open–closed principle states "software entities (classes, modules, functions, etc.) should be…