Dofactory.com
Dofactory.com
 Back to list
Views:   13.8K
Replies:  3
Archived

Prototype Pattern to copy/clone objects

I would like to know why following the DOF Prototype pattern is better suited than creating a simple and plain way of copying/cloning an object.

Given the following base class and creational factory method class PersonBirthFactory:


public class Person
{
  public Object Firstname{ get; set; }
  public Object Lastname{ get; set; }
}


public class PersonBirthFactory
  {
    public static CreatePerson()
    {
       Person p = new Person();
       p.FirstName = firstName;
       p.LastName = firstName;
       return p;
    }
}
The .NETOptimized version of the Prototype uses the following code to perform a deep copy: 

public object DeepCopy()
{
   MemoryStream stream = new MemoryStream();
   BinaryFormatter formatter = new BinaryFormatter();
   formatter.Serialize(stream, this);
   stream.Seek(0, SeekOrigin.Begin);
   object copy = formatter.Deserialize(stream);
   stream.Close();
   return copy;
}


A couple questions as to why I cannot use the following as opposed to the example above:

public object DeepCopy()
{
  Person p = new Person();
  p.FirstName = this.FirstName;
  p.LastName = this.FirstName;
  return p;

}
Why not use the following logic or something more simple than messing w/ MemoryStream, Serialization, Etc?

I can implement this pattern w/o doing research and wondering the benefits here, is it just a performance increase for using this?

In my current scenario the copy might happen at most 4 times in an hour, but when it happens they happen in quick sucession. I am mainly doing this to remove the logic  when creating a collection and need to fill in the missing items(cloned from other items) from the factory. The offending code is complex if/then/else/loops/etc... Best suited outside the factory in another object where I may need to use in other parts of the application down the road.

Looking for alternatives and would like to open a discussion on the best alternative.

TIA,

S

Net Wreck, Sep 20, 2010
Reply 1
Thanks a lot I did exactly as you said and it worked just amazing, see my output Thanks,

==================={STEP 1}==

Doe, John (Mother: Doe, Jane))

Doe, John (Mother: Doe, Jane))

Doe, John (Mother: Doe, Jane))

==================={STEP 2}==

Doe, John (Mother: Doe, Jen))

Doe, John (Mother: Doe, Jen))

Doe, John (Mother: Doe, Jane))




Krutisha Chovatiya, Mar 10, 2015
Reply 2
Thanks for this. Just replicated it and got:
==================={STEP 1}== Doe, John (Mother: Doe, Jane)) Doe, John (Mother: Doe, Jane)) Doe, John (Mother: Doe, Jane)) ==================={STEP 2}== Doe, John (Mother: Doe, Jen)) Doe, John (Mother: Doe, Jen)) Doe, John (Mother: Doe, Jane))

Thanks, Richard Wilcox
Matthew Carey, Oct 01, 2014
Reply 3
Hi,

I can think of two issues with your approach of copying the object.

1. You will need to modify your copy method each time a property changes in the Person class.
2. You copy the reference, not the object. This means that when the primary object has a member
   of a reference type and it changes, your copy will change too. (will provide example shortly).

Hope that helps.

UPDATE: Added Code example

First, the Person class:
[Serializable] 
      public class Person 
      { 
          public Object FirstName { get; set; } 
          public Object LastName { get; set; } 
          public Person Mother { get; set; } 

          public static Person CreatePerson(string firstName, string lastName) 
          { 
              var p = new Person { FirstName = firstName, LastName = lastName }; 
              return p; 
          } 

          public override string ToString() 
          { 
              if( Mother != null) 
              { 
                  return string.Format("{0}, {1} (Mother: {2})", LastName, FirstName, Mother); 
              } 
              else
              { 
                  return string.Format("{0}, {1})", LastName, FirstName); 
              } 
          } 
      } 


Helper methods for copying:
public static class PersonBirthFactory 
     { 
         public static Person DeepCopy(this Person person) 
         { 
             var stream = new MemoryStream(); 
             var formatter = new BinaryFormatter(); 

             formatter.Serialize(stream, person); 
             stream.Seek(0, SeekOrigin.Begin); 

             object copy = formatter.Deserialize(stream); 
             stream.Close(); 

             return copy as Person; 
         } 

         public static Person SimpleCopy(this Person person) 
         { 
             var p = new Person {FirstName = person.FirstName, LastName = person.LastName, Mother =  person.Mother}; 
             return p; 
         } 
     } 
Sample Console Application:

 
internal class Program 
    { 
        private static void Main(string[] args) 
        { 
            var john = Person.CreatePerson("John", "Doe"); 
            john.Mother = Person.CreatePerson("Jane", "Doe"); 
            //var jane = Person.CreatePerson("Jane", "Doe");

            var johnSimpleCopy = john.SimpleCopy(); 
            var johnDeepCopy = john.DeepCopy(); 


            System.Console.WriteLine("============{STEP 1}=="); 
            System.Console.WriteLine(john); 
            System.Console.WriteLine(johnSimpleCopy); 
            System.Console.WriteLine(johnDeepCopy); 

            john.Mother.FirstName = "Jen"; 
          
            System.Console.WriteLine("============{STEP 2}=="); 
            System.Console.WriteLine(john); 
            System.Console.WriteLine(johnSimpleCopy); 
            System.Console.WriteLine(johnDeepCopy); 
        } 
    } 

 The output:

==================={STEP 1}==
Doe, John (Mother: Doe, Jane))
Doe, John (Mother: Doe, Jane))
Doe, John (Mother: Doe, Jane))
==================={STEP 2}==
Doe, John (Mother: Doe, Jen))
Doe, John (Mother: Doe, Jen))
Doe, John (Mother: Doe, Jane))


As you can see from above, when chaning the Mother in
object "john" "johnsimplecopy" is also changed. This means
that your version of the copying only copies the reference
not the object itself.


Robert Blixt, Sep 21, 2010
Stay Inspired!
Join other developers and designers who have already signed up for our mailing list.
Terms     Privacy     Cookies       Do Not Sell       Licensing      
Made with    in Austin, Texas.  - vsn 44.0.0
© Data & Object Factory, LLC.