原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
原型模式结构演示
原型抽象类: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 }; } }