Thursday, October 17, 2013

C# - Shallow VS Deep Clone by Prototype Pattern

ความแตกต่างระหว่าง Shallow Clone กับ Deep Clone คือ

"'ShallowCopy' points to the same location in memory as 'Source' does. 'DeepCopy' points to a different location in memory, but the contents are the same."



[refer : http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy]

เรามาสร้าง Methods สำหรับการ Clone ด้วย Prototype Pattern กัน
1. สร้าง Application Console

2. เพิ่ม Class Color
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
public class Color : ICloneable
{
    private byte red, green, blue;
    public Color(byte red, byte green, byte blue)
    {
        this.red = red;
        this.green = green;
        this.blue = blue;
    }
    #region IColor.ICloneable Members
    public object Clone()
    {
        Console.WriteLine("Shallow copy of color RGB: {0,3},{1,3},{2,3}", red, green, blue);
        return this.MemberwiseClone();
    }
    #endregion
    #region Cloneable Members - Overloads
    public Object Clone(bool shallow)
    {
        if (shallow)
            return Clone();
        else
            return DeepCopy();
    }
    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();
        Console.WriteLine("*Deep*  copy of color RGB: {0,3},{1,3},{2,3}",
                ((Color)copy).red,
                ((Color)copy).green,
                ((Color)copy).blue);
        return copy;
    }
    #endregion
}
3. เพิ่ม Class ColorManager

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
public class ColorManager
{
    private Hashtable colors;
    public ColorManager()
    {
        colors = new Hashtable();
    }
    // Default Property
    public Color this[string name]
    {
        get
        {
            return (Color)colors[name];
        }
        set
        {
            colors.Add(name, value);
        }
    }
}
4. เรียกใช้ ColorManager จาก Main method

using System;
using System.Collections.Generic;
using System.Text;
namespace PrototypeConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            ColorManager colormanager = new ColorManager();
            colormanager["red"] = new Color(255, 0, 0);
            colormanager["green"] = new Color(0, 255, 0);
            Color color;
            string name = "red";
            color = (Color)colormanager[name].Clone(); //Shallow clone.
            Console.WriteLine(color.GetHashCode());
            name = "green";
            color = (Color)colormanager[name].Clone(false); //Deep clone.
            Console.WriteLine(color.GetHashCode());
            Console.Read();
        }
    }
}
5. รันโปรแกรม จะได้ผลลัพธ์ดังนี้

Class Diagram :


การทำ DeepClone จะมีประโยชน์สำหรับการทำ Cache ข้อมูล Object ที่เรียกใช้บ่อยๆ เพราะไม่จำเป็นต้องโหลดมาใหม่ทุกครั้งที่เรียกใช้ แต่การอ้างถึง Object ที่เก็บไว้ใน Cache หรือ Hash table ตรงๆ มันจะเป็น reference object คือ หากมีการแก้ไขค่าใน object ที่ถูกนำไปใช้ จะทำให้ค่าที่เก็บไว้ใน Cache เปลี่ยนไปด้วย ดังนั้นจึงต้องทำการ Clone object ออกมาจาก Cache แล้วจึงค่อยนำไปใช้ครับ

ลองไปประยุกต์ใช้กันดูครับ
NooM

No comments: