您的位置:首页 > 其它

设计模式——浅复制VS深复制

2015-12-08 11:28 483 查看

背景

   在学习原型模式的时候,采用了一个区别与其他模式的新方法。采用了“克隆(Clone)方法。通过实现ICloneable接口中的Clone()方法来达到克隆的目的。代码实现过程中,存在了我们所说的浅复制和深复制,下面看看有什么区别。

内容

代码实现

简历浅复制实现:

<span style="font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:24px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 浅复制
{
class Program
{
static void Main(string[] args)
{
Resume a = new Resume("大鸟");
a.SetPersonalInfo("男", "29");
a.SetWorkExperience("1992-2002", "XX公司");

Resume b = (Resume)a.Clone();
b.SetWorkExperience ("1992-2002","YY公司");

Resume c=(Resume )a.Clone ();
c.SetPersonalInfo ("男","24");
c.SetWorkExperience ("1995-2200","ZZ企业");

a.Display ();
b.Display ();
c.Display ();
Console .Read ();
}
}
//工作经历类
class WorkExperience
{
private string workDate;
public string WorkDate
{
get { return workDate; }
set { workDate = value; }
}

private string company;
public string Company
{
get { return company; }
set { company = value; }

}

}

//简历类
class Resume:ICloneable
{
private string name;
private string sex;
private string age;

private WorkExperience work;//引用“工作经历”对象

public Resume (string name )
{
this.name = name;
work = new WorkExperience();//在“简历”类实例化时间时实例化“工作经历”;
}
//设置个人信息
public void SetPersonalInfo(string sex, string age)
{
this.sex =sex ;
this .age =age ;

}

//设置工作经历
public void SetWorkExperience (string workDate,string company)
{
//调用此方法时,给对象的两属性赋值;
work.WorkDate = workDate;
work.Company = company;
}
//显示
public void Display()
{
Console.WriteLine("{0} {1} {2}", name, sex, age);
Console.WriteLine("工作经历:{0} {1}", work.WorkDate, work.Company);//显示时,显示“工作经历”的两属性的值。
}

public Object Clone()
{
return (Object)this.MemberwiseClone();
}
}
}
</span></span>
结果为:

           


简历深复制实现:

<span style="font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:24px;">//作者:周丽同
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 简历的深复制实现
{
class Program
{
static void Main(string[] args)
{
Resume a = new Resume("大鸟");
a.SetPersonalInfo("男", "29");
a.SetWorkeExperience("1998-2000", "XX公司");

Resume b = (Resume)a.Clone();
b.SetWorkeExperience("1998-2006", "YY公司");

Resume c = (Resume)a.Clone();
c.SetPersonalInfo("男", "24");
c.SetWorkeExperience("1998-2003", "ZZ企业");

a.Display();
b.Display();
c.Display();

Console.Read();
}
}

//改动的地方是:让工作经历也实现ICloneable接口
//工作经历类
class WorkExperience:ICloneable
{
private string workDate;
public string WorkDate
{
get { return workDate; }
set { workDate = value; }
}
private string company;
public string Company
{
get { return company; }
set { company = value; }
}

public Object Clone()
{
return (Object)this.MemberwiseClone();//“工作经历”类实现克隆方法;
}
}

//简历类
class Resume:ICloneable
{
private string name;
private string sex;
private string age;
private WorkExperience work;

public Resume (string name)
{
this.name = name;
work = new WorkExperience();
}
private Resume (WorkExperience work)
{
//提供克隆(Clone)方法调用的私有构造函数,以便克隆“工作经历”的数据;
this.work = (WorkExperience)work.Clone();

}

//设置个人信息
public void SetPersonalInfo(string sex,string age )
{
this.sex = sex;
this.age = age;
}
//设置工作经历

public void SetWorkeExperience(string workDate,string company)
{
work.WorkDate = workDate;
work.Company = company;
}
//显示

public void Display()
{
Console.WriteLine("{0} {1} {2}", name, sex, age);
Console.WriteLine("工作经历:{0} {1}", work.WorkDate, work.Company);
}

public Object Clone()
{
//调用私有的构造函数,让“工作经历”克隆完成,然后再给这个“简历”对象的相关字段赋值,
//最终返回一个深复制的简历对象;
Resume obj = new Resume(this.work);
obj.name = this.name;
obj.sex = this.sex;
obj.age = this.age;
return obj;
}
}

}</span></span>

结果是:                                   

                                          


   从上面的例子可以看出为什么对于值类型的对象,在克隆的时候可以轻易的复制过来,但是对于引用类型的,在克隆的时候复制过来的只是引用对象,而引用对象的数据是不会复制过来的。这里涉及到了什么是值类型和引用类型,它们在内存中是怎么“走的”。且看且分析:

 
值类型
引用类型
类型
结构体;数值类型(整型);浮点型;decimal型;bool型;枚举;可空类型;
数组;用户定义的类;接口;委托; Object类型;字符串类型;
是否可以包含null值


内存分配
分配在栈中
分配在堆中
主要职责
存储数据
传递引用(相当于指针)
适用场合
该类型的共有接口完全由一些数据成员存取属性定义;
永远不可能又子类;
不具有多态行为;
具有多态行为;
用于定义应用程序的行为;

浅复制和深复制含义

   在这里如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型的,则复制引用但不复制引用的对象。对于浅复制和深复制从下面的图来看:

浅复制:

                                                                                                   


深复制:

                                                                                                 


   通过上面的图和代码我们可以知道,可以根据我们的需要进行深复制和浅复制。当需要深复制的时候就需要加上一段对引用对象的深复制(克隆)。我理解深复制,在内存中的走向是: 


小结

   以上是本人关于c#中浅复制和深复制的一些理解,自己的理解还是有点表面,多多实践例子就会好很多,望各路大神提出宝贵意见。
1、不要害怕自己的想法不对,对不对试试就知道了。
2、学会站在巨人的肩膀上。
3、相信自己。

感谢您的宝贵时间~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: