标签:tool mat str style each 客户 targe row long
原型模式(Prototype)
定义:
原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。被复制的实例被称为原型,这个原型是可定制的。
Prototype Pattern也是一种创建型模式,它关注的是大量相同或相似对象的创建问题。应用原型模式就是建立一个原型,然后通过对原型来进行复制的方法,来产生一个和原型相同或相似的新对象,或者说用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
模式中的角色
抽象原型类(Abstract Prototype):提供一个克隆接口
具体原型类(Concrete Prototype): 实现了克隆接口的具体原型类
原型模式的优点有:
原型模式的缺点有:
原型模式的最重要缺点就是每一个类必须配备一个Clone方法,而且这个Clone方法需要对类的功能进行通盘考虑。这对全新的类来说不是很难,但对已有的类进行改造时,不一定是容易的事。
原型模式可以适用于以下情形:
浅拷贝与深拷贝
浅度复制(Shallow Copy):将原来对象中的所有字段逐个复制到一个新对象,如果字段是值类型,则简单地复制一个副本到新对象,改变新对象的值类型字段不会影响原对象;如果字段是引用类型,则复制的是引用,改变目标对象中引用类型字段的值将会影响原对象。
深度复制(Deep Copy):与浅复制不同之处在于对引用类型的处理,深复制将新对象中引用类型字段指向复制过的新对象,改变新对象中引用的任何对象,不会影响到原来的对象中对应字段的内容。
值类型和引用类型的知识点可以了解:值类型和引用类型深入理解
浅拷贝与深拷贝示例:
拷贝对象School和Student:
[Serializable] public class Student : ICloneable { private string name = "xxx"; private int age = 0; public string Name { get { return name; } set { name = value; } } public int Age { get { return age; } set { age = value; } } /// <summary> /// 新建对象实现克隆 /// </summary> /// <returns></returns> public Student NewClone() { return new Student() { age = this.age, name = this.name }; } /// <summary> /// 实现ICloneable接口 /// </summary> /// <returns></returns> public object Clone() { return this.MemberwiseClone(); } } [Serializable] public class School : ICloneable { private string m_Name = "init"; private int m_Number = -1; private Student m_Student; public string Name { get { return m_Name; } set { m_Name = value; } } public int Number { get { return m_Number; } set { m_Number = value; } } public Student Student { get { return m_Student; } set { m_Student = value; } } /// <summary> /// 新建对象实现克隆,如果属性是引用类型,需要一层层new赋值,直到属性是值类型为止 /// </summary> /// <returns></returns> public School NewClone() { return new School() { m_Name = this.m_Name, m_Number = this.Number, Student = this.Student.NewClone() }; } /// <summary> /// 实现ICloneable接口 /// </summary> /// <returns></returns> public object Clone() { return this.MemberwiseClone(); } }
序列化拷贝和反射拷贝:
public static class HelperTools { /// <summary> /// 序列化深拷贝 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="source"></param> /// <returns></returns> public static T SerializableClone<T>(T source) { if (!typeof(T).IsSerializable) { throw new ArgumentException("The type must be serializable.", source.GetType().ToString()); } if (Object.ReferenceEquals(source, null)) { return default(T); } IFormatter formatter = new BinaryFormatter(); using (MemoryStream ms = new MemoryStream()) { formatter.Serialize(ms, source); ms.Seek(0, SeekOrigin.Begin); return (T)formatter.Deserialize(ms); } } /// <summary> /// 反射属性浅拷贝 /// </summary> /// <param name="t"></param> /// <returns></returns> public static T PropertyClone<T>(T t) { if (Object.ReferenceEquals(t, null)) { return default(T); } Type type = t.GetType(); PropertyInfo[] propertyInfos = type.GetProperties(); Object obj = Activator.CreateInstance<T>(); Object p = type.InvokeMember("", BindingFlags.CreateInstance, null, t, null); foreach (PropertyInfo propertyInfo in propertyInfos) { if (propertyInfo.CanWrite) { object value = propertyInfo.GetValue(t, null); propertyInfo.SetValue(obj, value, null); } } return (T)obj; } }
public class Program { static void Main(string[] args) { School school = new School() { Name = "德源小学", Number = 0, Student = new Student() { Name = "兔基斯", Age = 18 } }; Console.WriteLine("************************原始值*****************************"); ShowSchoolInfo(school); Console.WriteLine("************************序列化深拷贝*****************************"); School serSchool = HelperTools.SerializableClone(school); serSchool.Name = "序列化"; serSchool.Number = 1; serSchool.Student.Name = "xuliehua"; serSchool.Student.Age = 20; ShowSchoolInfo(serSchool); ShowSchoolInfo(school); Console.WriteLine("************************新建对象深拷贝****************************"); School newSchool = (School)school.NewClone(); newSchool.Name = "new对象"; newSchool.Number = 2; newSchool.Student.Name = "newObject"; newSchool.Student.Age = 22; ShowSchoolInfo(newSchool); ShowSchoolInfo(school); Console.WriteLine("************************属性反射浅拷贝*****************************"); School proSchool = HelperTools.PropertyClone(school); proSchool.Name = "反射"; proSchool.Number = 3; proSchool.Student.Name = "fanshe"; proSchool.Student.Age = 21; ShowSchoolInfo(proSchool); ShowSchoolInfo(school); Console.WriteLine("************************克隆接口浅拷贝*****************************"); School cloneSchool = (School)school.Clone(); cloneSchool.Name = "克隆"; cloneSchool.Number = 4; cloneSchool.Student.Name = "kelong"; cloneSchool.Student.Age = 23; ShowSchoolInfo(cloneSchool); ShowSchoolInfo(school); Console.ReadLine(); } public static void ShowSchoolInfo(School school) { Console.WriteLine("学校名:{0}, 学校编号:{1}, 学生名字:{2}, 学生年龄:{3}", school.Name, school.Number, school.Student.Name, school.Student.Age); } }
、
注:实现克隆方法必须继承ICloneable接口,序列化的类必须标明特性[Serializable]
总结:
原型设计模式总算告一段落,从原型设计模式出发,深拷贝、浅拷贝,引用类型、值类型,拷贝方式,再回到起点原始设计模式,这一趟收获颇多。
C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝
标签:tool mat str style each 客户 targe row long
原文地址:http://www.cnblogs.com/zengming/p/6041128.html