设计模式之笔记--原型模式(Prototype)
原型模式(Prototype)
定义
原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
类图
描述
提供一个克隆自身的接口--Clone方法。
应用场景
定义一个学生类,包含一个值类型(int)的Age属性、两个引用类型Name(string)和Course属性。
public class Course { public string Name { get; set; } } public abstract class AbstractStudent { public string Name { get; set; } public int Age { get; set; } public Course Course { get; set; } public abstract AbstractStudent Clone(); } /// <summary> /// 浅拷贝 /// </summary> public class Student : AbstractStudent { public override AbstractStudent Clone() { Student student = new Student(); student.Name = base.Name; student.Age = base.Age; student.Course = base.Course; return student; } }
输出:
student : Jim 20 C++
student : Jim 20 C#
student1: Tom 21 C#
student : Jim 20 Java
student1: Tom 21 Java
从打印的结果可以看出,给原对象student拷贝一个新的student1对象并给student1属性赋值之后,原对象student的Age和Name没变,CourseName却变了。原因是拷贝之后,student把student1的Age和Name复制了一份,而student1的Course依然指向student的Course地址,所以,当student1的CourseName改变时,student的CourseName也随之改变,这就是浅拷贝。
但是在实际应用中,往往不希望发生这样的事情,也就是不能因为拷贝对象发生变化而影响到原对象。原因很简单,不能因为Tom选了C#这门课就要求Jim也必须把已经选的C++这门课改成C#。要解决这个问题,就需要拷贝一个全新的对象,即深拷贝。
下面通过序列化和反序列化来创建一个全新的student:
[Serializable] public class Course { public string Name { get; set; } } [Serializable] public abstract class AbstractStudent { public string Name { get; set; } public int Age { get; set; } public Course Course { get; set; } public abstract AbstractStudent Clone(); } [Serializable] /// <summary> /// 深拷贝 /// </summary> public class Student : AbstractStudent { public override AbstractStudent Clone() { using (Stream objectStream = new MemoryStream()) { IFormatter formatter = new BinaryFormatter(); formatter.Serialize(objectStream, this); objectStream.Seek(0, SeekOrigin.Begin); return formatter.Deserialize(objectStream) as Student; } } }
输出:
student : Jim 20 C++
student : Jim 20 C++
student1: Tom 21 C#
student : Jim 20 C++
student1: Tom 21 Java
浅拷贝和深拷贝的区别:
浅拷贝:对值类型和string类型直接拷贝,对引用类型共用同一个指针;两个对象之间存在耦合;
深拷贝:给对象拷贝一个全新的对象,两个对象之间的耦合度为0。