Saturday, June 11, 2016

Prototype Pattern


Prototype pattern is used to create an object from exiting object via cloning. Prototype pattern falls under creational pattern of GOF (Gang of Four) pattern.

When to use –


When you want to create an object by copying it from other object or prototype. So prototype act as master or blueprint and other objects created from master object are copies of that object. In short, Prototype pattern is used to clone objects. In real world example, a photocopy machine creates multiple copies from original document and you can independently use or send photocopies wherever you want to use original document.

Major components of prototype pattern are –


  • Prototype It’s an interface for cloning.
  • Concrete Prototype – Implements prototype interface and clone itself.
  • Client – Creates new object and ask to create clone of created object.

Prototype pattern is easy to implement. You can create your own interface which contains Clone method and use it as prototype. In below example I used ICloneable interface as Prototype.

Code –
public class Address
{
    public string Line1 { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public override string ToString()
    {
        return string.Format("Line1 : {0}, City : {1}, Country : {2}", Line1, City, Country);
    }
}
//ConcretePrototype
public class Person : ICloneable
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Address Address { get; set; }
    public object Clone()
    {
        return this.MemberwiseClone();
    }
    public override string ToString()
    {
        return string.Format("Name : {0}, Age : {1}, Address : {2}", Name, Age, Address.ToString());
    }
}
//Client
class Program
{
    static void Main(string[] args)
    {
        //New Person object
        Person p1 = new Person() { Name = "Mitesh", Age = 30, Address = new Address() { Line1 = "Addr 1", City = "Pune", Country = "India" } };
        Console.WriteLine("---------P1-----------");
        Console.WriteLine(p1.ToString());
        //Clone person object from existing P1 object
        Person p2 = (Person)p1.Clone();
        Console.WriteLine("---------P2-----------");
        Console.WriteLine(p2.ToString());
        //Modify P2 object
        p2.Name = "John";
        p2.Age = 40;
        p2.Address.Line1 = "A1";
        p2.Address.City = "Atlanta";
        p2.Address.Country = "USA";
        Console.WriteLine("---------P1-----------");
        Console.WriteLine(p1.ToString());
        Console.WriteLine("---------P2-----------");
        Console.WriteLine(p2.ToString());
        Console.ReadLine();
    }
}


Output –




In above example, I used MemberwiseClone () method which is available to all objects. This method creates shallow copy of an object. This method copies the values of all the fields and doesn’t copy references in the object points to. When object is simple and doesn’t contain any references of other objects then this method works very well. In above example I changed address of P2 object then it has also changed address of P1 object as well and this is not expected when you clone an object. To solve this problem, we need to use deep copy functionality to copy an object. See below example with little change in Clone method to implement deep copy.

Code –
public class Address
{
    public string Line1 { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public override string ToString()
    {
        return string.Format("Line1 : {0}, City : {1}, Country : {2}", Line1, City, Country);
    }
}
//ConcretePrototype
public class Person : ICloneable
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Address Address { get; set; }
    public object Clone()
    {
        //Shallow copy
        Person obj =  (Person)this.MemberwiseClone();
        //Deep copy
        obj.Address = new Address() { Line1 = this.Address.Line1, City = this.Address.City, Country = this.Address.Country };
        return obj;
    }
    public override string ToString()
    {
        return string.Format("Name : {0}, Age : {1}, Address : {2}", Name, Age, Address.ToString());
    }
}
//Client
class Program
{
    static void Main(string[] args)
    {
        //New Person object
        Person p1 = new Person() { Name = "Mitesh", Age = 30, Address = new Address() { Line1 = "Addr 1", City = "Pune", Country = "India" } };
        Console.WriteLine("---------P1-----------");
        Console.WriteLine(p1.ToString());
        //Clone person object from existing P1 object
        Person p2 = (Person)p1.Clone();
        Console.WriteLine("---------P2-----------");
        Console.WriteLine(p2.ToString());
        //Modify P2 object
        p2.Name = "John";
        p2.Age = 40;
        p2.Address.Line1 = "A1";
        p2.Address.City = "Atlanta";
        p2.Address.Country = "USA";
        Console.WriteLine("---------P1-----------");
        Console.WriteLine(p1.ToString());
        Console.WriteLine("---------P2-----------");
        Console.WriteLine(p2.ToString());
        Console.ReadLine();
    }
}

Output –











As you can see in above example, I made changes in Clone method and implemented deep copy functionality to copy reference object along with other values of object. Now you can see there is no change in P1 object’s address after changing P2 object’s address. It means implementing deep copy in prototype pattern we get brand new P2 object from prototype which has no relation with P1 object.

Difference between shallow copy and deep copy –


Shallow Copy
Deep Copy
Copies value types from source object to target object. It also copies object’s reference type as reference but not the referenced object itself.
Deep copy makes a complete copy of value types and reference types with actually coping it’s reference object.
Shallow copy objects are not 100% disconnected to its original object.
Deep copy objects are 100% disconnected to its original object.
MemeberwiseClone() method used to create Shallow copy of an object.
Need to override Clone method to modify object returned from MemeberwiseClone() to copy actual reference types.
Shallow copy is fast and less expensive
Deep copy is slow and expensive compare to shallow copy.
Shallow copy preferred when object has primitive types.
Deep copy is preferred when object has references to other objects.


Hope this article helps you to understand Prototype Pattern. Please leave your feedback in comments below.

References –

See Also –


No comments:

Post a Comment