设计模式培训之六:原型模式
查看文章索引请通过http://www.cnblogs.com/seesea125/archive/2012/04/17/2453256.html
一、什么是原型模式?
原型模式:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象
原型模式(Prototype结构图)
原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。
二、原型模式代码实现:
abstract class prototype { private string id; public prototype(string id) { this.id = id; } public string Id { get { return id; } set { id = value; } } public abstract prototype Clone();//抽象的关键就是这个Clone()这个方法. } class ConcretePrototype1:prototype { public ConcretePrototype1(string id) : base(id) { } public override prototype Clone() { return (prototype)this.MemberwiseClone();//创建当前对象的浅表副本。方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同一对象。 } class Program { static void Main(string[] args) { ConcretePrototype1 c1 = new ConcretePrototype1("123"); ConcretePrototype1 c2 = (ConcretePrototype1)c1.Clone();//克隆类 ConcretePrototype1的对象C1就能得到新的实例C1. Console.WriteLine(c2.Id); Console.Read(); } }
三、.NET 的应用 ICLoneable
但对于.NET而言,那个原型抽象类Prototype是用不着的,因为克隆实在是太常用了,所以.net在system命名空间中提供子ICloneable接口,其中就是唯一的一个方法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 object Clone() { return (object)this.MemberwiseClone(); } public void SetPersonInfo(string age, string sex) { this.sex = sex; this.age = age; } public void SetWorkExperience(string timearea, string company) { this.timearea = timearea; this.company = company; } public void display() { Console.WriteLine("{0} {1} {2} ", name, sex, age); Console.WriteLine("{0} {1}", timearea, company); } } class Program { static void Main(string[] args) { Resume re = new Resume("张久宪"); re.SetPersonInfo("21", "男"); re.SetWorkExperience("2011-2012", "YT"); re.display(); Resume re2 = (Resume)re.Clone(); re2.SetWorkExperience("2012-2013", "其它"); re2.display(); Console.Read(); } }
四、原型模式的优点
每new一次,都需要执行一次构造函数,如果构造函数的执行时间很长,那么多次的执行这个初始化操作就实在是太低效了。一般在初始化的信息不发生变化的情况下,克隆是最好的办法。这即隐藏了对象的细节,又对性能是大大的提高。
意思就是不用重新初始化对象,而是动态地获取对象运行时的状态。
1. 浅复制与深复制
MemberwiseClone()方法是这样,如果字段是值类型的,则对该字段执行逐位复制,如查字段是引用类型,则复制引用但不自制引用的对象:因此,原始对象及其复本引用同一对象。
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; } } #region ICloneable 成员 public object Clone() { return (WorkExperience)this.MemberwiseClone(); } #endregion } class Resume:ICloneable { private string name; private string age; private string sex; private WorkExperience work; public Resume(string name) { this.name = name; work = new WorkExperience(); } private Resume(WorkExperience work) { this.work = (WorkExperience)work.Clone(); } public void setPersonInfo(string age, string sex) { this.age = age; this.sex = sex; } public void setWorkExperience(string workdate, string company) { work.WorkDate = workdate; work.Company = company; } public void Display() { Console.WriteLine("{0} {1} {2}", name, age, sex); Console.WriteLine("{0} {1}", work.WorkDate, work.Company); } #region ICloneable 成员 public object Clone() { Resume obj = new Resume(this.work); obj.name = this.name; obj.age = this.age; obj.sex = this.sex; return obj; } #endregion } 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; } } #region ICloneable 成员 public object Clone() { return (WorkExperience)this.MemberwiseClone(); //工作经历类实现克隆方法 } #endregion } class Resume:ICloneable { private string name; private string age; private string sex; private WorkExperience work; public Resume(string name) { this.name = name; work = new WorkExperience(); } private Resume(WorkExperience work) { this.work = (WorkExperience)work.Clone(); //提供Clone方法调用私有构造函数,以便克隆“工作经历的数据” } public void setPersonInfo(string age, string sex) { this.age = age; this.sex = sex; } public void setWorkExperience(string workdate, string company) { work.WorkDate = workdate; work.Company = company; } public void Display() { Console.WriteLine("{0} {1} {2}", name, age, sex); Console.WriteLine("{0} {1}", work.WorkDate, work.Company); } #region ICloneable 成员 public object Clone() { Resume obj = new Resume(this.work); //调用私有方法,让“工作经历”克隆完成,然后再给这个简历对象的相关数据字段赋值,最终返回一个深复制的简历对象. obj.name = this.name; obj.age = this.age; obj.sex = this.sex; return obj; } #endregion } class Program { static void Main(string[] args) { Resume re = new Resume("张久宪"); re.setPersonInfo("12","男"); re.setWorkExperience("2011","YT"); re.Display(); Resume re1 = (Resume)re.Clone(); re1.setPersonInfo("12", "男"); re1.setWorkExperience("2012", "YT1"); re1.Display(); Resume re2 = (Resume)re.Clone(); re2.setPersonInfo("12", "男"); re2.setWorkExperience("2013", "YT2"); re2.Display(); Console.Read(); } }
2. 原型模式的应用.
DataSet他就有Clone()和copy() 。Clone()方法用来复制的DataSet的结构,但不复制DataSet的数据,实现了原型械的浅复制。Copy()方法不但复制结构,也复制数据,其实就是实现了原型模式的深复制