原型模式(Prototype) 類圖 描述 原型模式: 提供一個克隆自身的介面--Clone方法。 應用場景 定義一個學生類,包含一個值類型(int)的Age屬性、兩個引用類型Name(string)和Course屬性。 輸出: student:Jim 20 C++ student:Jim 20 C ...
原型模式(Prototype)
類圖
描述
原型模式:
提供一個克隆自身的介面--Clone方法。
應用場景
定義一個學生類,包含一個值類型(int)的Age屬性、兩個引用類型Name(string)和Course屬性。
public class Course { public string Name { get; set; } } public class Student : ICloneable { public string Name { get; set; } public int Age { get; set; } public Course Course { get; set; } public object Clone() { return this.MemberwiseClone(); } } static void Main(string[] args) { string value = ConfigurationManager.AppSettings["prototypePattern"]; Student student = (Student)Assembly.Load(value.Substring(0, value.IndexOf('.'))).CreateInstance(value); student.Name = "Jim"; student.Age = 20; student.Course = new Course() { Name = "C++" }; Console.WriteLine("student:" + student.Name + "\t" + student.Age + "\t" + student.Course.Name); Console.WriteLine(); Student student1 = (Student)student.Clone(); student1.Name = "Tom"; student1.Age = 21; student1.Course.Name = "C#"; Console.WriteLine("student:" + student.Name + "\t" + student.Age + "\t" + student.Course.Name); Console.WriteLine("student1:" + student1.Name + "\t" + student1.Age + "\t" + student1.Course.Name); Console.WriteLine(); student1.Course.Name = "Java"; Console.WriteLine("student:" + student.Name + "\t" + student.Age + "\t" + student.Course.Name); Console.WriteLine("student1:" + student1.Name + "\t" + student1.Age + "\t" + student1.Course.Name); }
輸出:
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類和Course類小改一下,通過序列化和反序列化來創建一個全新的student:
[Serializable] public class Course { public string Name { get; set; } } [Serializable] public class Student : ICloneable { public string Name { get; set; } public int Age { get; set; } public Course Course { get; set; } public object Clone() { using (Stream objectStream = new MemoryStream()) { IFormatter formatter = new BinaryFormatter(); formatter.Serialize(objectStream, this); objectStream.Seek(0, SeekOrigin.Begin); return formatter.Deserialize(objectStream); } } }
輸出:
student:Jim 20 C++
student:Jim 20 C++
student1:Tom 21 C#
student:Jim 20 C++
student1:Tom 21 Java
淺拷貝和深拷貝的區別:
淺拷貝:對值類型和string類型直接拷貝,對引用類型共用同一個指針;兩個對象之間存在耦合;
深拷貝:給對象拷貝一個全新的對象,兩個對象之間的耦合度為0。