設計模式之原型模式
Intro 簡介
原型模式,用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象
原型模式其實就是從一個對象再創建另外一個可定製的對象而且不需要知道任何創建的細節。
實現方式
實現方式大致如下:
在 c# 中可以藉助 ICloneable
接口和 MemberwiseClone
方法來方便的實現原型模式,需要注意的是這個方法是淺複製,當對象內嵌套了另外一個對象的時候,尤其需要注意。
// 淺複製
public object Clone() => MemberwiseClone();
示例
簡單的簡歷,所有的字段屬性都是簡單類型
public class SimpleResume : ICloneable
{
private string _name;
private string _email;
private string _timePeriod;
private string _company;
public void SetPersonalInfo(string name, string email)
{
_name = name;
_email = email;
}
public void SetWorkExperience(string company, string timePeriod)
{
_company = company;
_timePeriod = timePeriod;
}
public void Display()
{
Console.WriteLine($"{_name} {_email}");
Console.WriteLine($"工作經歷:{_timePeriod} {_company}");
}
public object Clone() => MemberwiseClone();
}
var resume = new SimpleResume();
resume.SetPersonalInfo("小明", "[email protected]");
resume.SetWorkExperience("xxx公司", "1990~2000");
resume.Display();
var resume1 = (SimpleResume)resume.Clone();
resume1.SetWorkExperience("xxx企業", "1998~1999");
resume1.Display();
var resume2 = (SimpleResume)resume.Clone();
resume2.SetPersonalInfo("xiaohong", "[email protected]");
resume2.Display();
深複製示例,下面是一個複雜一些的簡歷,裏面包含了一個 WorkExperience
是另外一個類型,直接淺複製的話_workExperience 仍然指向原來的引用,來看下面的示例是怎麼解決這個問題的
public class WorkExperience : ICloneable
{
public string TimePeriod { get; set; }
public string Company { get; set; }
public object Clone() => MemberwiseClone();
}
public class ComplexResume : ICloneable
{
private readonly WorkExperience _workExperience;
private string _name;
private string _email;
public ComplexResume() => _workExperience = new WorkExperience();
private ComplexResume(WorkExperience workExperience) => _workExperience = (WorkExperience)workExperience.Clone();
public void SetPersonalInfo(string name, string email)
{
_name = name;
_email = email;
}
public void SetWorkExperience(string comapny, string timePeriod)
{
_workExperience.Company = comapny;
_workExperience.TimePeriod = timePeriod;
}
public void Show()
{
Console.WriteLine($"{_name} {_email}");
Console.WriteLine($"Work Experience: {_workExperience.Company} {_workExperience.TimePeriod}");
}
public object Clone() => new ComplexResume(_workExperience)
{
_name = _name,
_email = _email
};
}
#region deep copy
var complexResume = new ComplexResume();
complexResume.SetPersonalInfo("xiaoming", "[email protected]");
complexResume.SetWorkExperience("xiaomingTecch", "2001~2005");
complexResume.Show();
var complexResume1 = (ComplexResume)complexResume.Clone();
complexResume1.SetPersonalInfo("xiaohong", "[email protected]");
complexResume1.Show();
#endregion deep copy
More
有人一定會說序列化了,當然,你用序列化也是可以做到的,序列化再反序列化得到的也是一個全新的對象,但是對於簡單的對象,我覺得用上面這種方式就足夠了,而且這種方式是直接操作內存,把對應的數據內存複製一份更加高效
我們之前搞的推送服務裏有一個推送請求的對象,會頻繁的使用序列化反序列化來複制一個新的對象,這個場景就很適合使用原型模式來進行處理,高效的創建一個新的對象。
在需要頻繁的複製對象的場景下,都可以考慮使用原型模式來創建新的對象