zoukankan      html  css  js  c++  java
  • 对象的复制

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

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

      

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

    原型类:

    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

  • 相关阅读:
    PHP学习(字符串和变量)
    一个操作配置文件(Reg,ini,XML)的类
    Indy中判断邮件来源
    PHP学习(MSSQL数据库连接)
    辛辛苦苦,写了个INNO的安装脚本
    php连接sqlserver
    Sql Server 使用CTE实现递归查询
    使用序列化和反序列化机制深度复制对象
    ASP.NET中不常用的另类绑定方法<%$ %>
    google map事件监听
  • 原文地址:https://www.cnblogs.com/netqq/p/2704721.html
Copyright © 2011-2022 走看看