原型模式就是依照样本复制一个出来。就像复印机原理一样的。当你需要一个同样的对象时。你并不需要重新构建这个类。你直接使用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、序列化后,地址完全不同。和实例化结果相等。都指向了不同地址。