对象的复制

 

一般说要复制对象,不知道大家怎么做,我的 第一个想法是,实例化一个新的对象,不过这不是最优的做法。

其实,我所要说的是一种模式----原型模式。

  

       “原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节”。也许上边这个图你看不懂,对我也看不懂,所以不做解释了,具体咱们看一个示例:

原型类:

View Code
abstract class Prototype
{
    private String id;
    public Prototype(String id)
    {
        this.id = id;
    }

    public string Id
    {
        get { return id; }
    }

    public abstract Prototype Clone();//创ä¡ä建¡§一°?个?抽¨¦象¨®方¤?法¤¡§,ê?这a个?方¤?法¤¡§返¤¦Ì回?当Ì¡À前¡ã对?象¨®自Á?身¦¨ª

}

具体原型类
class ConcretePrototypel : Prototype
{
    public ConcretePrototypel(string id): base(id)
    {

    }

    public override Prototype Clone()
    {
        return (Prototype)this.MemberwiseClone();
    }
}

客户端代码

View Code
public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {

        ConcretePrototypel p1 = new ConcretePrototypel("I");
        ConcretePrototypel c1 = (ConcretePrototypel)p1.Clone(); //从䨮对?象¨®p1开a始º?拷?贝À¡ä数ºy据Y

        Response.Write(c1.Id);
        Response.End();
    }
}

输出结果就是一个  I

 

这样就可以不用实例化 ConcretePrototypel(c1对象) 而是直接克隆对象p1

       因为这种克隆非常常用,所以.net  在System命名空间中提供了ICloneable接口,其中就是唯一的一个方法Clone(),这样只需要实现这个接口就可以完成原型模式

 

       我们来看看这个示例

       定义一个简历类

View Code
    public class Resume:ICloneable
{
    public Resume()
    {
        //
        //TODO: 在¨²此ä?处ä|添¬¨ª加¨®构1造¨¬函¡¥数ºy逻?辑-
        //
    }

    private string name;
    private string sex;
    private string age;
    private string timeArea;
    private string company;

    public Resume(string name)
    {
        this.name = name;
    }

    //设¦¨¨置?个?人¨?信?息¡é
    public void SetPersonalInfo(String sex, String age)
    {
        this.sex = sex;
        this.age = age;
    }

    //设¦¨¨置?工¡è作Á¡Â经-历¤¨²
    public void SetWorkExperience(String timeArea, String company)
    {
        this.timeArea = timeArea;
        this.company = company;
    }

    //显?示º?
    public string  Display()
    {
        return string.Format("{0} {1} {2},工¡è作Á¡Â经-历¤¨²:êo{3} {4}", name, sex, age, timeArea ,company);
    }

    public object Clone()
    {
        return (object)this.MemberwiseClone();
    }
}

客户端
protected void Page_Load(object sender, EventArgs e)
    {

        Resume a = new Resume("娟¨º儿¨´");
        a.SetPersonalInfo("女?","25");
        a.SetWorkExperience("1987-2012","xzx公?司?");

        Resume b = (Resume)a.Clone();
        b.SetWorkExperience("1998-2206","yy企¨®业°¦Ì");

        Resume c = (Resume)a.Clone();
        b.SetPersonalInfo("男D", "24");

        Response.Write(a.Display()+"</br>");
        Response.Write(b.Display() + "</br>");
        Response.Write(c.Display() + "</br>");


}

运行结果:

 

这样一来,客户端的代码清爽了许多,程序效率也高了许多,不用每个对象都New一次了。

一般在初始化的信息不发生变化的情况下,克隆是最好的办法。这既隐藏了对象创建的细节,又对性能是大大的提高了

他的实现原理是,不重新初始化,而是动态的获取对象运行时的状态

       二、浅复制与深复制

MemberwiseClone()方法是这样,如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用对象;因此,原始对象及其复本引用同一对象。

就是说如果类中有对象是引用类型,那么引用的对象数据时不会被克隆的。

 

我们修改一下上边简历类的代码,创建一个工作经历的类 WorkExperience

 

View Code
 1 public class WorkExperience
 2 {
 3     public WorkExperience()
 4     {
 5         //
 6         //TODO: 在¨²此ä?处ä|添¬¨ª加¨®构1造¨¬函¡¥数ºy逻?辑-
 7         //
 8     }
 9 
10     private String workDate;
11     public String WorkDate
12     {
13         get { return workDate; }
14         set { workDate = value; }
15     }
16 
17     private String company;
18     public String Company
19     {
20         get { return company; }
21         set { company = value; }
22     }
23 }
24 
25 
26 修改简历类
27 
28 public class NewResume : ICloneable
29 {
30     public NewResume()
31     {
32         //
33         //TODO: 在¨²此ä?处ä|添¬¨ª加¨®构1造¨¬函¡¥数ºy逻?辑-
34         //
35     }
36 
37     private string name;
38     private string sex;
39     private string age;
40   
41 
42     private WorkExperience work;
43 
44     public NewResume(string name)
45     {
46         this.name = name;
47         work = new WorkExperience();     //实º¦Ì例¤y化¡¥工¡è作Á¡Â经-历¤¨²
48     }
49 
50     //设¦¨¨置?个?人¨?信?息¡é
51     public void SetPersonalInfo(String sex, String age)
52     {
53         this.sex = sex;
54         this.age = age;
55     }
56 
57     //设¦¨¨置?工¡è作Á¡Â经-历¤¨²
58     public void SetWorkExperience(String workDate, String company)
59     {
60         work.WorkDate = workDate;
61         work.Company = company;
62     }
63 
64     //显?示º?
65     public string Display()
66     {
67         return string.Format("{0} {1} {2},工¡è作Á¡Â经-历¤¨²:êo{3} {4}", name, sex, age, work.WorkDate,work.Company);
68     }
69 
70     public object Clone()
71     {
72         return (object)this.MemberwiseClone();
73     }
74 }
75 
76 
77 客户端:
78       NewResume a = new NewResume("娟¨º儿¨´");
79         a.SetPersonalInfo("女?","25");
80         a.SetWorkExperience("1987-2012","xzx公?司?");
81 
82         NewResume b = (NewResume)a.Clone();
83         b.SetWorkExperience("1998-2206","yy企¨®业°¦Ì");
84 
85         NewResume c = (NewResume)a.Clone();
86         b.SetPersonalInfo("男D", "24");
87 
88         Response.Write(a.Display()+"</br>");
89         Response.Write(b.Display() + "</br>");
90         Response.Write(c.Display() + "</br>");

运行结果

我们在来看先深复制

 

将NewResume类稍微修改一下,为其增加一个构造函数,并修改Clone()方法

 

构造函数:

public NewResume_01(WorkExperience work)

    {

 

        this.work = work;     //实º¦Ì例¤y化¡¥工¡è作Á¡Â经-历¤¨²

    }

 

Clone() 方法

 

public object Clone()

    {

        NewResume_01 obj = new NewResume_01(this.work);

        obj.name = name;

        obj.sex = sex;

        obj.age = age;

        return obj;

    }

 

修改一下WorkExperience(工作经历类)类

为其增加一个方法,用于返回自身

public object Clone()

    {

        return this.MemberwiseClone();

    }

ok,我们看看运行效果

 

 文件下载路径:https://files.cnblogs.com/netqq/Test.zip

 

posted @ 2012-09-26 21:39  Myisqq  阅读(1509)  评论(8编辑  收藏  举报