Blog / Design Patterns
The Prototype Design Pattern in C# and .Net
  • Dec 10, 2020
  • 70
  • 83

In this post, we will learn about the third pattern in Creational Design Patterns - Prototype. Let's see what is the Prototype Pattern, when and how we implement it in C# and .Net.

Note: Code can be downloaded at my Github


Advertisement
 


1. What is the Prototype Design Pattern?

With the Prototype Design Pattern, programs are able to create a new instance of a class from an existing object. By doing so, it's easier to create an instance of a complex object that maybe costly to create a new one.

Prototype Design Pattern specifies the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.


2. When to use Prototype Design Pattern

For example, in a car manufacturing industry, it would be difficult to produce a car from scratch. Rather than that, car companies usually make a clone from a previous car model and enhance it to produce a new and better car model every year. The same is apply to your programs if there is a complex class which is costly (in term of time and space) to be newly initiated.

Let's consider below example when you may want to create a new object by copying from an existing object. We have a Person and an Address class like below:

public class Person
{
    public string Name { get; set; }
 
    public Address Address { get; set; }
 
    public Person(string name, Address address)
    {
        Name = name;
        Address = address;
    }
 
    public override string ToString()
    {
        return $"Name: {Name}, Address: {Address.Street}, {Address.City} - {Address.PostalCode.ToString()}";
    }
}
 
public class Address
{
    public string Street { get; set; }
 
    public string City { get; set; }
 
    public int PostalCode { get; set; }
 
    public Address(string street, string city, int postalCode)
    {
        Street = street;
        City = city;
        PostalCode = postalCode;
    }
}


Now, we will create 2 objects from the Person class. The 2 objects are from the same household so the only different is their names.

class Program
{
    static void Main(string[] args)
    {
        Person person1= new Person("Lucas", new Address("Avenue O", "Brooklyn", 11204));
 
        Person person2= person1;
        person2.Name = "Eric";
        Console.WriteLine(person1.ToString());
        Console.WriteLine(person2.ToString());   
    }
}


The above code will print out both people with the name Eric which is incorrect. The reason is the program just copies the reference (shallow copy) of the first person object to create the second one. We should implement Prototype Pattern by using ICloneable or Copy Constructor to make things work.


3. Implementing Prototype Design Pattern by using ICloneable

In the Person class, we can inherit the ICloneable interface which then can implement the Clone method. The Clone method creates a new object that is a copy of the current instance.

public class PersonWithICloneable : ICloneable
{
    public string Name { get; set; }
 
    public AddressWithICloneable Address { get; set; }
 
    public PersonWithICloneable(string name, AddressWithICloneable address)
    {
        Name = name;
        Address = address;
    }
 
    public override string ToString()
    {
        return $"Name: {Name}, Address: {Address.Street}, {Address.City} - {Address.PostalCode.ToString()}";
    }
 
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}
 
public class AddressWithICloneable : ICloneable
{
    public string Street { get; set; }
 
    public string City { get; set; }
 
    public int PostalCode { get; set; }
 
    public AddressWithICloneable(string street, string city, int postalCode)
    {
        Street = street;
        City = city;
        PostalCode = postalCode;
    }
 
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

Now, we will create 2 objects from the PersonWithICloneable class. The cloned person object will be updated with a different name and street address.

class Program
{
    static void Main(string[] args)
    {
        PersonWithICloneable personWithICloneable1 = new PersonWithICloneable("Lucas", new AddressWithICloneable("Avenue O", "Brooklyn", 11204));
 
        PersonWithICloneable personWithICloneable2 = (PersonWithICloneable)personWithICloneable1.Clone();
        personWithICloneable2.Name = "Eric";
        personWithICloneable2.Address.Street = "Sethlow";
 
        Console.WriteLine(personWithICloneable1.ToString());
        Console.WriteLine(personWithICloneable2.ToString());
    }
}


The result show that the 2 people have different names now. However, it seems like the street address is shallow copied again! This is a problem with using ICloneable. Let's take a look at how we resolve this problem by using a copy constructor.


4. Implementing Prototype Design Pattern by using Copy Constructor

Create PersonWithCopyConstructor and AddressWithCopyConstructor classes like below:

public class PersonWithCopyConstructor
{
    public string Name { get; set; }
 
    public AddressWithCopyConstructor Address { get; set; }
 
    public PersonWithCopyConstructor(string name, AddressWithCopyConstructor address)
    {
        Name = name;
        Address = address;
    }
 
    public PersonWithCopyConstructor(PersonWithCopyConstructor personWithCopyConstructor)
    {
        Name = personWithCopyConstructor.Name;
        Address = new AddressWithCopyConstructor(personWithCopyConstructor.Address);
    }
 
    public override string ToString()
    {
        return $"Name: {Name}, Address: {Address.Street}, {Address.City} - {Address.PostalCode.ToString()}";
    }
}
 
public class AddressWithCopyConstructor
{
    public string Street { get; set; }
 
    public string City { get; set; }
 
    public int PostalCode { get; set; }
 
    public AddressWithCopyConstructor(string street, string city, int postalCode)
    {
        Street = street;
        City = city;
        PostalCode = postalCode;
    }
 
    public AddressWithCopyConstructor(AddressWithCopyConstructor address)
    {
        Street = address.Street;
        City = address.City;
        PostalCode = address.PostalCode;
    }
}

Now, we will do something similar to update the second person name and street address. 

class Program
{
    static void Main(string[] args)
    {
        PersonWithCopyConstructor personWithCopyConstructor1 = new PersonWithCopyConstructor("Lucas", new AddressWithCopyConstructor("Avenue O", "Brooklyn", 11204));
 
        PersonWithCopyConstructor personWithCopyConstructor2 = new PersonWithCopyConstructor(personWithCopyConstructor1);
        personWithCopyConstructor2.Name = "Eric";
        personWithCopyConstructor2.Address.Street = "Sethlow";
 
        Console.WriteLine(personWithCopyConstructor1.ToString());
        Console.WriteLine(personWithCopyConstructor2.ToString());
    }
}

This time, it's print out the information correctly for both persons. It's safe to implement Prototype Pattern by using a Copy Constructor.

Great! So we have learnt another pattern in Creational Category. I hope this is helpful! Please let me know your thoughts by commenting in the section below! See you next time!


There are some benefits of keeping both UI and API parts in the same place for small projects. In this article, I will explain how I did to deploy Angular Web and ASP .Net Core API in the same folder ...

Using cherry-pick to select specific commits for your Pull Request.1. Create a new branch based on the target of the Pull Requestgit branch cherry-branch origin/master2. Switch to a new branchgit chec ...

I got CORS error after publishing my API and Angular app to IIS even though CORS is enabled and the origins of the Angular app is added. Below is how I resolved this issue.Just simple, make sure you s ...

After deployment Angular and API on IIS, it's working fine unless I refresh the page. Once refreshed, the web encountered 404 error. In this article, I will explain how to resolve this.Since Angular i ...

1. The Situation:Error Message: Pulse Secure Application failed to load Java. Please install correct JRE version.Description: This issue happens when I'm using a M1 Mac with a correct version of ...

Accelerated Mobile Pages (AMP) focuses on delivering static content from publishers as quickly as possible and possibly rewards early adopters with a boost in rank. Let's see how to implement it ...

Below is how to decrypt/convert a Hex string value into text using VB.Net:Decrypting Hex string value to string in VB.Net Function HexToString(ByVal hex As String) As String Dim text As New Sy ...

After a month of publishing on Google Play, Jungle Words has made it to the Top Android Games To Try Out In April 2021. Please check it out! GameKeys.netGameKeys is a website which introduces gam ...

Centering HTML elements is an important aspect for anything involving designing with CSS. There are various methods of centering things, however, it also depends on the elements that you are working w ...