【原型模式】:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性
当要实例化的类是在运行时刻指定时,例如,通过动态装载;
或者为了避免创建一个与产品类层次平行的工厂类层次时;
或者当一个类的实例只能有几个不同状态组合中的一种时。
建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
【实现代码】
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
//原型模式:其实就是从一个对象再创建另一个可制定的对象,而且不需知道任何创建的细节。
//原型类;
abstract class Prototype
{
private string id;
public Prototype(string id)
{
this.id = id;
}
public string Id
{
get { return id; }
}
public abstract Prototype Copy();//抽象类关键就是有这样一个Clone方法;
}
//具体原型类;
class ConcretePtototypel : Prototype
{
public ConcretePtototypel(string id)
: base(id)
{ }
public override Prototype Copy()
{
return (Prototype)this.MemberwiseClone();
/*MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,
然后将当前对象的非静态字段复制到该新对象。
如果字段是值类型的,则对该字段执行逐位复制。
如果字段是引用类型,则复制引用但不复制引用的对象;
因此,原始对象及其复本引用同一对象。*/
}
}
//客户代码
class Program
{
static void Main(string[] args)
{
ConcretePtototypel p1 = new ConcretePtototypel("I");
//克隆类ConcretePtototypel的对象p1就能得到新实例c1;
ConcretePtototypel c1 = (ConcretePtototypel)p1.Copy();
Console.WriteLine("Cloned:{0}",c1.Id);
Console.Read();
}
}
}
【实例代码2.】
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
//由于.NET在System命名空间中提供了IConeable接口,
//其中唯一的一个方法就是Clone。这样就只需实现这个接口就可以完成原型模式了。
//简历类;
class Resume:ICloneable
{
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.age = age;
this.sex = sex;
}
//设置工作经历;
public void SetWorkPerience(string timeArea, string company)
{
this.company = company;
this.timeArea = timeArea;
}
//显示;
public void Display()
{
Console.WriteLine("{0}{1}{2}",name ,sex,age);
Console.WriteLine("工作经历:{0} {1}",timeArea,company);
}
public Object Clone()
{
return (Object)this.MemberwiseClone();
}
//客户代码
class Program
{
static void Main(string[] args)
{
Resume a = new Resume("小山");
a.SetPersonalInfo("男","22");
a.SetWorkPerience("2006-2007","大一年级");
Resume b = (Resume)a.Clone();
b.SetPersonalInfo("张小山","22");
b.SetWorkPerience("2007-2008","大二年级");
Resume c = (Resume)a.Clone();
c.SetPersonalInfo("张 山","22");
c.SetWorkPerience("2008-2009","大三年级");
a.Display();
b.Display();
c.Display();
Console.Read();
}
}
}
}
【浅表复制】
MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。使用实现 ICloneable 接口的类执行对象的浅表或深层复制。
【实现代码】:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
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.age = age;
this.sex = sex;
}
//设置工作经历;
public void SetWorkPerience(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();
}
//工作经历类;
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 Program
{
static void Main(string[] args)
{
Resume a = new Resume("小山");
a.SetPersonalInfo("男","22");
a.SetWorkPerience("2006-2007","大一年级");
Resume b = (Resume)a.Clone();
b.SetPersonalInfo("张小山","22");
b.SetWorkPerience("2007-2008","大二年级");
Resume c = (Resume)a.Clone();
c.SetPersonalInfo("张山","22");
c.SetWorkPerience("2008-2009","大三年级");
a.Display();
b.Display();
c.Display();
/这里b和c都克隆于a,但当它们都设置了工作经历时,我们希望的结果是现实三个不同的结果;但是,结果它们却是一样的,都显示最后的设置。因为只是复制了引用,没有真正复制对象!
Console.Read();
}
}
}
}
【深表复制】
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
//工作经历类;
class WorkExperience:ICloneable // ①让“工作经历”类实现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.age = age;
this.sex = sex;
}
//设置工作经历;
public void SetWorkPerience(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;
}
//客户代码
class Program
{
static void Main(string[] args)
{
Resume a = new Resume("小山");
a.SetPersonalInfo("男","22");
a.SetWorkPerience("2006-2007","大一年级");
Resume b = (Resume)a.Clone();
b.SetPersonalInfo("张小山","22");
b.SetWorkPerience("2007-2008","大二年级");
Resume c = (Resume)a.Clone();
c.SetPersonalInfo("张山","22");
c.SetWorkPerience("2008-2009","大三年级");
a.Display();
b.Display();
c.Display();
Console.Read();
}
}
}
}