C#设计模式-2创建型模式-2.6原型模式(Prototype Pattern)
2.6.1 定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
2.6.2 场景模拟
写一个简历类,必须要有姓名,可以设置性别和年龄,可以设置工作经历,最终需要三份简历。
2.6.3 代码演示
class Program { static void Main(string[] args) { Resume resume1 = new Resume("hobe"); resume1.SetPersonalInfo("男", 35); resume1.SetWorkExperience("2009-2014","XX公司"); Resume resume2 = (Resume)resume1.Clone(); resume2.SetWorkExperience("2014-2016","YY公司"); Resume resume3 = (Resume)resume1.Clone(); resume3.SetPersonalInfo("男", 32); resume1.Display(); resume2.Display(); resume3.Display(); Console.ReadLine(); } } public class Resume : ICloneable { public string Name { get; set; } public string Sex { get; set; } public int Age { get; set; } public string TimeArea { get; set; } public string Company { get; set; } public Resume(string name) { this.Name = name; } public void SetPersonalInfo(string sex,int 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.ToString()}"); Console.WriteLine($"工作经历:{TimeArea} {Company}"); } public object Clone() { return this.MemberwiseClone(); } }
上面代码实现的浅拷贝的方式,浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅拷贝,那么这两个对象将引用同一个字符串,而深拷贝是对对象实例中字段引用的对象也进行拷贝,如果一个对象有一个指向字符串的字段,并且我们对该对象进行了深拷贝的话,那么我们将创建一个对象和一个新的字符串,新的对象将引用新的字符串。也就是说,执行深拷贝创建的新对象和原来对象不会共享任何东西,改变一个对象对另外一个对象没有任何影响,而执行浅拷贝创建的新对象与原来对象共享成员,改变一个对象,另外一个对象的成员也会改变。
深复制的应用场景:
加一个工作经历类,这个类中有时间区间和公司名称,简历类中直接调用这个对象
using System; namespace PrototypePattern { class Program { static void Main(string[] args) { Resume resume1 = new Resume("hobe"); resume1.SetPersonalInfo("男", 35); resume1.SetWorkExperience("2009-2014","XX公司"); Resume resume2 = (Resume)resume1.Clone(); resume2.SetWorkExperience("2014-2016","YY公司"); Resume resume3 = (Resume)resume1.Clone(); resume3.SetWorkExperience("2014-2016", "ZZ公司"); resume1.Display(); resume2.Display(); resume3.Display(); Console.ReadLine(); } } public class WorkExperience : ICloneable { public string WorkDate { get; set; } public string Company { get; set; } public object Clone() { return this.MemberwiseClone(); } } public class Resume : ICloneable { public string Name { get; set; } public string Sex { get; set; } public int Age { get; set; } public WorkExperience Work { get; set; } public Resume(string name) { this.Name = name; this.Work = new WorkExperience(); } private Resume(WorkExperience work) { this.Work = (WorkExperience)work.Clone(); } public void SetPersonalInfo(string sex,int 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.ToString()}"); Console.WriteLine($"工作经历:{Work.WorkDate} {Work.Company}"); } public object Clone() { Resume resume = new Resume(this.Work); resume.Name = this.Name; resume.Sex = this.Sex; resume.Age = this.Age; return resume; } } }
2.6.4 优缺点
优点:
原型模式向客户隐藏了创建新实例的复杂性
原型模式允许动态增加或较少产品类。
原型模式简化了实例的创建结构,工厂方法模式需要有一个与产品类等级结构相同的等级结构,而原型模式不需要这样。
产品类不需要事先确定产品的等级结构,因为原型模式适用于任何的等级结构
缺点:
每个类必须配备一个克隆方法
配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。