設(shè)計模式培訓(xùn)之六:原型模式
查看文章索引請通過http://www.rzrgm.cn/seesea125/archive/2012/04/17/2453256.html
一、什么是原型模式?
原型模式:用原型實例指定創(chuàng)建對象的種類,并通過拷貝這些原型創(chuàng)建新的對象
原型模式(Prototype結(jié)構(gòu)圖)
原型模式其實就是從一個對象再創(chuàng)建另外一個可定制的對象,而且不需知道任何創(chuàng)建的細(xì)節(jié)。
二、原型模式代碼實現(xiàn):
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();//抽象的關(guān)鍵就是這個Clone()這個方法. } class ConcretePrototype1:prototype { public ConcretePrototype1(string id) : base(id) { } public override prototype Clone() { return (prototype)this.MemberwiseClone();//創(chuàng)建當(dāng)前對象的淺表副本。方法是創(chuàng)建一個新對象,然后將當(dāng)前對象的非靜態(tài)字段復(fù)制到該新對象。如果字段是值類型的,則對該字段執(zhí)行逐位復(fù)制。如果字段是引用類型,則復(fù)制引用但不復(fù)制引用的對象;因此,原始對象及其副本引用同一對象。 } 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 的應(yīng)用 ICLoneable
但對于.NET而言,那個原型抽象類Prototype是用不著的,因為克隆實在是太常用了,所以.net在system命名空間中提供子ICloneable接口,其中就是唯一的一個方法Clone().這樣你就只需要實現(xiàn)這個接口就可以完成原型模式了.
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(); } }
四、原型模式的優(yōu)點
每new一次,都需要執(zhí)行一次構(gòu)造函數(shù),如果構(gòu)造函數(shù)的執(zhí)行時間很長,那么多次的執(zhí)行這個初始化操作就實在是太低效了。一般在初始化的信息不發(fā)生變化的情況下,克隆是最好的辦法。這即隱藏了對象的細(xì)節(jié),又對性能是大大的提高。
意思就是不用重新初始化對象,而是動態(tài)地獲取對象運行時的狀態(tài)。
1. 淺復(fù)制與深復(fù)制
MemberwiseClone()方法是這樣,如果字段是值類型的,則對該字段執(zhí)行逐位復(fù)制,如查字段是引用類型,則復(fù)制引用但不自制引用的對象:因此,原始對象及其復(fù)本引用同一對象。
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(); //工作經(jīng)歷類實現(xiàn)克隆方法 } #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方法調(diào)用私有構(gòu)造函數(shù),以便克隆“工作經(jīng)歷的數(shù)據(jù)” } 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); //調(diào)用私有方法,讓“工作經(jīng)歷”克隆完成,然后再給這個簡歷對象的相關(guān)數(shù)據(jù)字段賦值,最終返回一個深復(fù)制的簡歷對象. 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. 原型模式的應(yīng)用.
DataSet他就有Clone()和copy() 。Clone()方法用來復(fù)制的DataSet的結(jié)構(gòu),但不復(fù)制DataSet的數(shù)據(jù),實現(xiàn)了原型械的淺復(fù)制。Copy()方法不但復(fù)制結(jié)構(gòu),也復(fù)制數(shù)據(jù),其實就是實現(xiàn)了原型模式的深復(fù)制


浙公網(wǎng)安備 33010602011771號