對象的復制


 

一般說要復制對象,不知道大家怎么做,我的 第一個想法是,實例化一個新的對象,不過這不是最優的做法。

其實,我所要說的是一種模式----原型模式。

  

       “原型模式其實就是從一個對象再創建另外一個可定制的對象,而且不需要知道任何創建的細節”。也許上邊這個圖你看不懂,對我也看不懂,所以不做解釋了,具體咱們看一個示例:

原型類:

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,我們看看運行效果

 

 文件下載路徑:http://files.cnblogs.com/netqq/Test.zip

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM