大話設計模式-原型模式
阿新 • • 發佈:2018-11-28
原型模式
用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。
原型模式其實就是從一個物件再建立另外一個可定製的物件,而且不需要知道任何建立的細節。
原型模式結構演示
原型抽象類:Prototype
abstract class Prototype{ public string Id { get; set; } public Prototype(string id) => Id = id; public abstract Prototype Clone(); }
具體原型類:ConcretePrototype1
class ConcretePrototype1 : Prototype{ public ConcretePrototype1(string id) : base(id){ } public override Prototype Clone() => (Prototype)this.MemberwiseClone(); }
測試類:Program
ConcretePrototype1 p1 = new ConcretePrototype1("A"); ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone(); Console.WriteLine("Cloned:"+c1.Id); //結果 Cloned:A
對於.NET而言,原型抽象類Prototypr使用不到的,因為克隆很常用,.NET在System名稱空間提供了ICloneable介面,其中一個方法就是Clone(),只需要實現這個介面就可以完成原型克隆了。
簡歷的原型實現
簡歷類:Resume
class Resume : ICloneable{ private string name, sex, age, timeArea, company; public Resume(string name) => this.name = name;public void SetPersonalInfo(string sex, string age){ this.sex = sex; this.age = age; } public void SetWorkExperience(string timeArea,string company){ this.timeArea = timeArea; this.company = company; } public void Display(){ Console.WriteLine($"{name},{sex},{age}"); Console.WriteLine($"工作經歷:{timeArea},{company}"); } public object Clone() => MemberwiseClone(); }
測試類:Program
//簡歷a Resume a = new Resume("曹丞相"); a.SetPersonalInfo("男","29"); a.SetWorkExperience("2017-2018", "網易公司"); //簡歷b,修改工作經歷 Resume b = (Resume)a.Clone(); b.SetWorkExperience("2018-2019", "騰訊公司"); //簡歷c,修改年齡 Resume c = (Resume)a.Clone(); c.SetPersonalInfo("男", "30"); //顯示 a.Display(); b.Display(); c.Display(); //測試結果 曹丞相,男,29 工作經歷:2017-2018,網易公司 曹丞相,男,29 工作經歷:2018-2019,騰訊公司 曹丞相,男,30 工作經歷:2017-2018,網易公司
淺複製與深複製
MemberwiseClone()方法是這樣的,如果欄位是值型別就對該欄位執行逐位複製,如果欄位是引用型別,則複製引用但不復制引用的物件,因此原始物件及其副本引用同一物件。即淺複製。
簡歷的深複製實現
工作經歷類:WorkExperience
假如增加工作經歷類,將工作時間和公司封裝到工作經歷類。
class WorkExperience : ICloneable{ public string WorkDate { get; set; } public string Conpany { get; set; } public Object Clone() => MemberwiseClone(); }
簡歷類:Resume
修改簡歷類的欄位、構造器、設定工作經歷方法和Clone方法。
class Resume : ICloneable{ private string name, sex, age; private WorkExperience work; //構造器 public Resume(string name){ this.name = name; work = new WorkExperience(); } public Resume(WorkExperience work) => this.work = (WorkExperience)work.Clone(); //設定個人資訊 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( $"{name},{sex},{age + Environment.NewLine}工作經歷:{work.WorkDate},{work.Company}" ); //克隆簡歷 public object Clone() { //呼叫私有的構造方法,讓工作經歷類克隆完成 //再給簡歷物件的欄位複製,最終返回一個深複製的簡歷物件 return new Resume(work){ name = name, sex = sex, age = age }; } }