設計模式之原型模式
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
有人一定會說序列化了,當然,你用序列化也是可以做到的,序列化再反序列化得到的也是一個全新的物件,但是對于簡單的物件,我覺得用上面這種方式就足夠了,而且這種方式是直接操作記憶體,把對應的資料記憶體復制一份更加高效
我們之前搞的推送服務里有一個推送請求的物件,會頻繁的使用序列化反序列化來復制一個新的物件,這個場景就很適合使用原型模式來進行處理,高效的創建一個新的物件,
在需要頻繁的復制物件的場景下,都可以考慮使用原型模式來創建新的物件
Reference
- https://github.com/WeihanLi/DesignPatterns/tree/master/CreatePattern/PrototypePattern
- https://docs.microsoft.com/en-us/dotnet/api/system.object.memberwiseclone?view=netcore-3.1
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/3498.html
標籤:C#
