设计模式——原型模式

来源:互联网 发布:ubuntu 17.04 u盘安装 编辑:程序博客网 时间:2024/05/16 10:49
转载请注明出处!
原型模式说明:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
下面是原型模式基本代码:

//抽象原型类 abstract class Prototype { public string Id; public Prototype(string id) { Id = id; } public abstract Prototype Clone(); //克隆方法 }

//具体原型,继承自Prototype

class ConcretePrototype1 : Prototype { public ConcretePrototype1(string id) : base(id) { } public override Prototype Clone() {

//创建一个对象的浅表副本,不复制静态字段,值类型逐位复制,引用类型只复制引用,但不复制对象 return (Prototype)this.MemberwiseClone(); } }

//客户端代码

class MainProgram { void Main() { ConcretePrototype1 c1 = new ConcretePrototype1("IQ007"); ConcretePrototype1 c2 = (ConcretePrototype1)c1.Clone(); //克隆类 Console.WriteLine("Cloned: {0}", c2.Id); Console.Read(); } }

原型模式即在一个原型的基础上,克隆这些原型从而创建新的对象。因为程序设计中克隆太常用了,所以.NET在System命名空间中提供了ICloneable接口,其中就是唯一的一个方法Clone(),这样只需要实现这个接口就可以完成原型模式了。需要注意:MemberwiseClone()方法是浅复制操作,如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象;因此原始对象及其副本引用同一对象。
下面是原型模式的一个例子,求职时我们都是把一份简历模版复制多份,然后修改其中的不同信息即可。
先看一下“浅复制”的原型模式实现代码:

//工作经历类 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; } } }

//简历类,也实现ICloneable接口 class Resume : ICloneable { private string name; private string sex; private string age; private WorkExperience workExp;//引用工作经历对象 public Resume(string name) { this.name = name; workExp = new WorkExperience(); } //设置个人信息 public void SetPersonalInfo(string sex, string age) { this.sex = sex; this.age = age; } //设置工作经历 public void SetWorkExp(string workDate, string workCompany) { workExp.WorkDate = workDate; workExp.Company = workCompany; } //显示 public void Display() { Console.WriteLine("{0} {1} {2}", name, sex, age); Console.WriteLine("工作经历:{0} {1}", workExp.WorkDate, workExp.Company); } public object Clone() { return (Object)this.MemberwiseClone(); } }

//客户端代码 class Program { static void Main(string[] args) { //简历的浅复制实现 Resume res1 = new Resume("IQ007"); res1.SetPersonalInfo("男", "24"); res1.SetWorkExp("2015-10-8", "云南天游科技有限公司"); Resume res2 = (Resume)res1.Clone(); //复制简历1 res2.SetWorkExp("2016-3-1", "上海智幻软件科技有限公司"); Resume res3 = (Resume)res1.Clone(); //复制简历1 res3.SetPersonalInfo("男", "25"); res3.SetWorkExp("2016-6-12", "青岛爱维互动信息技术有限公司"); res1.Display(); res2.Display(); res3.Display(); Console.ReadKey(); } }

运行结果如下:
设计模式——原型模式 - IQ007伟哥 - IQ007伟哥的博客
 
可以发现,虽然在客户端克隆原型后的赋值不同,但是输出的信息除了年龄,其他所有信息都是最后一次修改的结果,因为年龄是整数(值类型),克隆后会复制新的值类型,而其他信息是引用类型,克隆后只复制引用,导致对象 的引用类型会保存最后一次的赋值。

下面是“深复制”的实现代码:

//简历的深复制实现,实现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() //工作经历类,实现Clone方法 { return this.MemberwiseClone(); } }

//简历类,也实现ICloneable接口 class Resume : ICloneable { private string name; private string sex; private string age; private WorkExperience workExp; public Resume(string name) { this.name = name; workExp = new WorkExperience(); } //提供Clone方法调用的私有构造函数,以便克隆“工作经历”数据 private Resume(WorkExperience work) { this.workExp = (WorkExperience)work.Clone(); //深复制:把引用对象的变量指向复制过来的新对象 } //设置个人信息 public void SetPersonalInfo(string sex, string age) { this.sex = sex; this.age = age; } //设置工作经历 public void SetWorkExp(string workDate, string workCompany) { workExp.WorkDate = workDate; workExp.Company = workCompany; } //显示 public void Display() { Console.WriteLine("{0} {1} {2}", name, sex, age); Console.WriteLine("工作经历:{0} {1}", workExp.WorkDate, workExp.Company); } public object Clone() { //Clone函数调用私有的构造方法,创建一个新的Resume对象, //让workExp克隆完成,然后再给这个“简历”对象的相关字段赋值,最终返回一个深复制的“简历对象” Resume resume = new Resume(this.workExp); resume.name = this.name; resume.sex = this.sex; resume.age = this.age; return resume; } }

客户端代码不变,运行结果如下:
设计模式——原型模式 - IQ007伟哥 - IQ007伟哥的博客
 可以发现,运行结果显示的三个简历信息不一样。
在一些特定的场合,会经常涉及深复制或浅复制,比如说,数据集对象DataSet,它就有Clone()方法和Copy()方法,其中Clone()方法是用来赋值DataSet的结构,但不复制DataSet的数据,实现了原型模式的浅复制;Copy()方法不但复制结构,也复制数据,实现了原型模式的深复制。
原创粉丝点击