设计模式(六)原型模式

原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。

 1 // 原型类
 2 abstract class Prototype
 3 {
 4   private string id;
 5   
 6   public Prototype(string id)
 7   {
 8     this.id = id;
 9   }
10 
11   public string Id
12   {
13     get { return id; }
14   }
15   // 抽象类关键就是有这样一个 Clone 方法
16   public  abstract  Prototype  Clone();
17 }
18 
19 // 具体原型类
20 class ConcretePrototype1 : Prototype
21 {
22   public ConcretePrototype1(string id) : base(id)
23   {
24   }
25   // 创建当前对象的浅表副本。方法是创建一个新对象,然后将当前对象的非静态字段复制到该对象。如果字段是值类型的,则对该字段执行逐位复制。 
26   // 如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同一对象。
27   public override Prototype Clone()
28   {
29     return  (Prototype)this.MemberwiseClone();
30   }
31 }
32 
33 // 客户端代码
34 Static void Main(string[] args)
35 {
36   ConcretePrototype1  p1 = new ConcretePrototype1( "I" );
37 
38   // 克隆类 ConcretePrototype1 的对象 p1 就能得到新的实例 c1
39   ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();
40 
41   Console.WriteLine("Cloned: {0}",  c1.Id );
42   Console.Read();
43 }

 对于 .NET 而言,原型抽象类 Prototype 是用不着的。因为 .NET 在 System 命名空间中提供了 ICloneable 接口,其中就是唯一的一个方法 Clone(),只需要实现这个接口就可以完成原型模式了。

一般在初始化的信息不发生变化的情况下,克隆是最好的方法。克隆不用重新初始化对象,而是动态地获得对象运行时的状态。这样既隐藏了对象创建的细节,又提高了性能。

浅复制

MemberwiseClone() 方法是这样:如果字段是值类型的,则对该字段执行逐位复制;如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。浅复制使得被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。

深复制

深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。深复制要深入很多层,需要事先就考虑好,而且要当心出现循环引用的问题。

【例】简历的深复制实现

 实现代码

 1 // 工作经历类,实现 ICloneable 接口
 2 class WorkExperence : ICloneable
 3 {
 4   private string workDate;
 5   public string WorkDate
 6   {
 7     get { return workDate; }
 8     set { workDate = value; }
 9   }
10 
11   private string company;
12   public string Company
13   {
14     get { return company; }
15     set { company = value; }    
16   }
17 
18   public  Object  Clone()
19   {
20     return (Object)this.MemberwiseClone();
21   }
22 }
23 
24 //  简历类
25 class Resume : ICloneable
26 {
27   private string name;
28   private string sex;
29   private string age;
30 
31   private  WorkExperience  work;
32 
33   public  Resume(string  name)
34   {
35     this.name = name;
36     work = new  WorkExperience();
37   }  
38   // 提供 Clone 方法调用的私有构造函数,以便克隆 “工作经历” 的数据
39   public  Resume(WorkExperience  work)
40   {
41     this.work = (WorkExperience)work.Clone();
42   }  
43   // 设置个人信息
44   public  void  SetPersonalInfo(string sex, string age)
45   {
46     this.sex = sex;
47     this.age = age;
48   }
49   // 设置工作经历
50   public  void  SetWorkExperience(string workDate, string company)
51   {
52     work.WorkDate = workDate;
53     work.Company = company;
54   }
55   // 显示
56   public  void  Display()
57   {
58     Console.WriteLine("{0} {1} {2}", name, sex, age);
59     Console.WriteLine("工作经历:{0} {1} ", work.WorkDate, work.Company );
60   }
61   //
62   public  Object  Clone()
63   {
64     Resume  obj = new Resume(this.work);
65     obj.name = this.name;
66     obj.sex = this.sex;
67     obj.age = this.age;
68     return  obj;
69   }
70 
71 }

 【总结】

在一些特定场合,会经常涉及深复制或浅复制。比如说,数据集对象 DataSet,它就有 Clone() 方法和 Copy() 方法,Clone() 方法用来复制 DataSet 的结构,但不复制 DataSet 的数据,实现了原型模式的浅复制。Copy() 方法不但复制结构,也复制数据,其实就是实现了原型模式的深复制。

posted @ 2015-06-18 11:30  壬子木  阅读(118)  评论(0)    收藏  举报