Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Prototype Design Pattern Implementation

Suggested Videos
Part 12 - Builder Design Pattern Implementation - Text - Slides
Part 13 - Fluent Builder Design Pattern - Text - Slides
Part 14 - ProtoType Design Pattern Introduction - Text - Slides

In this video we will discuss
  1. Significance of Copying
  2. MemberwiseClone Method and ICloneable Interface
  3. Prototype Design Pattern Example

Significance of Copying 
  • The idea of using copy is to create a new object of the same type without knowing the exact type of the object we are invoking
  • Shallow Copy and Deep copy plays prominent role in copying the objects in Prototype Design Pattern
  • Creating the required object once and by creating the subsequent required objects by cloning helps reducing the time for creating the objects
  • With Prototype design pattern, based on the requirement situations we can save memory by cloning the objects
    Example : Adapting to clone an object which consists of many strings (immutable) is a good idea than creating an object

MemberwiseClone Method
  • The MemberwiseClone method is part of system.object and creates a shallow copy of the given object 
  • MemberwiseClone Method copies the nonstatic fields of the chosen object to the new object
  • In the process of copying, if a field is a value type, a bit by bit copy of the field is performed. If a field is reference type, the reference is copied but the referenced object is not
ICloneable Interface
  • The ICloneable interface provides with a customized implementation that creates copy of an existing object 
  • The ICloneable interface contains one member, the clone method, which is intended to provide support beyond MemberwiseClone method
Step 1 : Create Employee and Address Objects. Implement ICloneable clone method using MemberwiseClone method

public partial class Employee
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public int DepartmentID { get; set; }

    public override string ToString()
    {
        return string.Format(" Name : {0}  " + "DepartmentID : {1}  {2} ",
            this.Name, this.DepartmentID.ToString(), AddressDetails.ToString());
    }
}
public partial class Employee : ICloneable
{
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}
public partial class Employee
{
    public Address AddressDetails { get; set; }
}

public class Address
{
    public Address() { }

    public int DoorNumber { get; set; }
    public int StreetNumber { get; set; }
    public int Zipcode { get; set; }
    public string Country { get; set; }
    public override string ToString()
    {
        return string.Format("AddressDetails : Door : {0}, Street: {1}, ZipCode : {2}," +
            " Country : {3}", this.DoorNumber, this.StreetNumber, this.Zipcode.ToString(),
            this.Country);
    }
}

Step 2 : Create a method named ShallowCopy() and implement the below code

public static void ShallowCopy()
{
    Employee empJohn = new Employee()
    {
        Id = Guid.NewGuid(),
        Name = "John",
        DepartmentID = 150,
    };

    Console.WriteLine(empJohn.ToString());

    Employee empSam = (Employee)empJohn.Clone();
    empSam.Name = "Sam Paul";
    Console.WriteLine(empSam.ToString());

    Console.WriteLine("Changed Johns DepartmentID to 161");
    empJohn.DepartmentID = 161;
    Console.WriteLine(empJohn.ToString());
    Console.WriteLine(empSam.ToString());

    Console.ReadLine();
}

Step 3 : Invoke ShallowCopy() method from the Console Main program and observe the below output. Notice that change in department doesn’t impact the target object.

prototype design pattern real time example

Step 4 : Now Reference the address object in the employee object and create a new ShallowCopyRef method and implement the below code.

public static void ShallowCopyRef()
{
    Employee empJohn = new Employee()
    {
        Id = Guid.NewGuid(),
        Name = "John",
        DepartmentID = 150,
        AddressDetails = new Address()
        {
            DoorNumber = 10,
            StreetNumber = 20,
            Zipcode = 90025,
            Country = "US"
        }
    };

    Console.WriteLine(empJohn.ToString());

    Employee empSam = (Employee)empJohn.Clone();
    empSam.Name = "Sam Paul";
    empSam.DepartmentID = 151;
    empSam.AddressDetails.StreetNumber = 21;
    empSam.AddressDetails.DoorNumber = 11;

    Console.WriteLine(empSam.ToString()); 

    Console.WriteLine("Modified Details of John");
    empJohn.AddressDetails.DoorNumber = 30;
    empJohn.AddressDetails.StreetNumber = 40; 

    empJohn.DepartmentID = 160;
    Console.WriteLine(empJohn.ToString());
    Console.WriteLine(empSam.ToString());

    Console.ReadLine();
}

Step 5 : Invoke the ShallowCopyRef method from main program and observe the output. Change in address details has propagated to address of target object. This means, MemberwiseClone copies the reference and not the address object itself

what is shallow copy and deep copy

Step 6 : To Address the DeepCopy requirement implement the custom CloneablePrototype implementation as shown below.

public abstract class CloneablePrototype<T>
{
    // Shallow copy
    public T Clone()
    {
        return (T)this.MemberwiseClone();
    }

    // Deep Copy
    public T DeepCopy()
    {
        string result = JsonConvert.SerializeObject(this);
        return JsonConvert.DeserializeObject<T>(result);
    }
}

public partial class Employee : CloneablePrototype<Employee>
{
    public Guid Id { get; set; }
    public string Name { get; set; }

    public int DepartmentID { get; set; }

    public Address AddressDetails { get; set; }
    public override string ToString()
    {
        return string.Format(" Name : {0}, DepartmentID : {1} , " +
            "Address : {2}",
            this.Name, this.DepartmentID.ToString(),
            this.AddressDetails.ToString());
    }
}

Step 7 : Create PrototypeDemo method and implement the code as shown below. The only change is to replace the ShallowCopy with DeepCopy method.

private static void PrototypeDemo()
{
    Employee empJohn = new Employee()
    {
        Id = Guid.NewGuid(),
        Name = "John",
        DepartmentID = 150,
        AddressDetails = new Address()
        {
            DoorNumber = 10,
            StreetNumber = 20,
            Zipcode = 90025,
            Country = "US"
        }
    };

    Console.WriteLine(empJohn.ToString());

    Employee empSam = (Employee)empJohn.DeepCopy();

    empSam.Name = "Sam Paul";
    empSam.DepartmentID = 151;
    empSam.AddressDetails.StreetNumber = 21;
    empSam.AddressDetails.DoorNumber = 11;

    Console.WriteLine(empSam.ToString());

    Console.WriteLine("Modified Details of John");
    empJohn.AddressDetails.DoorNumber = 30;
    empJohn.AddressDetails.StreetNumber = 40;

    empJohn.DepartmentID = 160;
    Console.WriteLine(empJohn.ToString());
    Console.WriteLine(empSam.ToString());
    Console.ReadLine();
}

Step 8 : Run the application and notice that the change in address details in source object doesn’t impact the Target object.

shallow copy vs deep copy

Step 9 : With this, we have successfully implemented the Prototype design pattern.

In the next video we will discuss the SOLID Principles and Structural Design Patterns.

Design Patterns tutorial for beginners

No comments:

Post a Comment

It would be great if you can help share these free resources