原型模式就是依照样本复制一个出来。就像复印机原理一样的。当你需要一个同样的对象时。你并不需要重新构建这个类。你直接使用CLONE就可以得到这个类。

在实际编程中,由于在某些情况下构建一个对象很难,这个时候你就要用到原型模式了,直接复制。

应用场景:

1、节约工作量(类似WINDOWS 安装,和直接GHOST来安装。原理是一样的,当一个对象,你建造的时候很麻烦,很复杂,你直接用CLONE一下就行了。节省大量时间)

2、快照,恢复(就像你的数据库快照一样,如果出现任何问题,我就恢复到原来正确的时间。当一个对象,你准备修改,但是当你知道修改后可能会出错,会返回。这个时候你就要用CLONE做一个副本)

 

复制分为两种

1、深度复制

深度复制就是,值类型和引用类型都同时指向不同的内存地址

2、浅复制

浅复制就是,值类型是新内存地址,而引用类型是同一个内存地址,因此你修改了值类型正本和副本相互不影响,你修改了引用类型正本和副本相互影响。

 

两种复制方法在实际当中的使用:

 [Serializable]
    public class PropertyOne
    {
        public string Name { get; set; }

        public int ID { get; set; }

        public ClassDes class1 { get; set; }

        /// <summary>
        /// 浅克隆,只能克隆值类型
        /// </summary>
        /// <returns></returns>
        public PropertyOne Clone()
        {
            return (PropertyOne)this.MemberwiseClone();
        }

        /// <summary>
        /// 深度克隆,值类型和引用类型都可以克隆
        /// </summary>
        /// <returns></returns>
        public T DeepClone<T>()
        {
            ///使用序列化和反序列化来做深度克隆
            return SerializeHelper.DeserializeBinaryFormatter<T>(SerializeHelper.SerializeBinaryFormatter(this));
        }
    }


    [Serializable]
    public class ClassDes
    {
        public int SID { get; set; }
    }

 

1、添加序列化支持属性。Serializable

实际使用:

PropertyOne PropertyOne1 = new PropertyOne();
            PropertyOne1.Name = "PropertyOne1";
            PropertyOne1.ID = 1;
            PropertyOne1.class1 = new ClassDes() { SID = 111 };

            PropertyOne PropertyOne2 = PropertyOne1.Clone();

            Console.WriteLine("原值");
            Console.WriteLine("PropertyOne1.SID={0}", PropertyOne1.class1.SID);
            Console.WriteLine("PropertyOne2.SID={0}", PropertyOne2.class1.SID);


            PropertyOne2.Name = "PropertyOne2";
            PropertyOne2.ID = 2;
            ///这个地方只要修改。序列化就出错,Message: "在分析完成之前就遇到流结尾。"
            PropertyOne2.class1.SID = 222;

            Console.WriteLine("修改后");
            Console.WriteLine("PropertyOne1.SID={0}", PropertyOne1.class1.SID);
            Console.WriteLine("PropertyOne2.SID={0}", PropertyOne2.class1.SID);

            PropertyOne PropertyOne3 = PropertyOne1.Clone();
            PropertyOne3.Name = "PropertyOne3";
            PropertyOne3.ID = 3;
            ///这个地方给class1指向了一个全新的地址
            PropertyOne3.class1 = new ClassDes() { SID = 333 };

            Console.WriteLine("实例后的");
            Console.WriteLine("PropertyOne1.SID={0}", PropertyOne1.class1.SID);
            Console.WriteLine("PropertyOne2.SID={0}", PropertyOne2.class1.SID);
            Console.WriteLine("PropertyOne3.SID={0}", PropertyOne3.class1.SID);

            PropertyOne PropertyOne4 = PropertyOne1.DeepClone<PropertyOne>();
            PropertyOne4.Name = "PropertyOne4";
            PropertyOne4.ID = 3;
            PropertyOne4.class1.SID = 444;

            Console.WriteLine("用序列化深克隆之后的");
            Console.WriteLine("PropertyOne1.SID={0}", PropertyOne1.class1.SID);
            Console.WriteLine("PropertyOne2.SID={0}", PropertyOne2.class1.SID);
            Console.WriteLine("PropertyOne3.SID={0}", PropertyOne3.class1.SID);
            Console.WriteLine("PropertyOne4.SID={0}", PropertyOne4.class1.SID);
            Console.Read();

 

结果

图解

1、原值和修改后的值,完全是一个地址,同时发生变化。原理在于值类型和引用类型的地址指向。浅克隆引用类型仍然指向相同的地址

2、实例化后的情况。如果给克隆体引用类型指向一个新对象(实际是新地址)。结果是不同的

3、序列化后,地址完全不同。和实例化结果相等。都指向了不同地址。

posted on 2015-12-23 09:48  梦回过去  阅读(288)  评论(0编辑  收藏  举报