原型模式屬於創建型設計模式,其核心概念是「用原型實例指定創建對象的種類,並通過拷貝這個原型來創建新的對象」。簡單來說,當建立新物件的成本較高(例如複雜的初始化、資料庫查詢、網路請求)時,我們可以透過複製現有的物件(原型)來快速產生新實例,並根據需求修改其屬性。
ICloneable。假設我們有一個 MessageModel 實體類別,包含訊息內容與發布時間。我們將示範如何實作淺層與深層複製。
using System;
namespace Pattern.Prototype
{
public class MessageModel
{
public string Message { get; set; }
public DateTime PublishTime { get; set; }
public MessageModel(string msg, DateTime pt)
{
Message = msg;
PublishTime = pt;
}
}
}
淺層複製僅複製值類型欄位,參考類型仍指向同一個記憶體位址。C# 透過 MemberwiseClone() 實作。
using System;
namespace Pattern.Prototype
{
public class ShallowCopy : ICloneable
{
public MessageModel MessageModel { get; set; }
public object Clone()
{
return this.MemberwiseClone(); // 淺層複製
}
}
}
深層複製會遞迴複製參考類型的物件,確保新舊物件完全獨立。這裡我們在 Clone() 中手動建立新的 MessageModel。
using System;
namespace Pattern.Prototype
{
public class DeepCopy : ICloneable
{
public MessageModel MessageModel { get; set; }
public DeepCopy() { }
public DeepCopy(MessageModel mm)
{
MessageModel = mm;
}
public object Clone()
{
// 建立全新的 MessageModel 實例,達成深層複製
return new DeepCopy(new MessageModel(MessageModel.Message, MessageModel.PublishTime));
}
}
}
using System;
using System.Web.UI;
using Pattern.Prototype;
public partial class Prototype : Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("ShallowCopy 演示:<br />");
ShowShallowCopy();
Response.Write("DeepCopy 演示:<br />");
ShowDeepCopy();
}
private void ShowShallowCopy()
{
var sc = new ShallowCopy { MessageModel = new MessageModel("ShallowCopy", DateTime.Now) };
var sc2 = (ShallowCopy)sc.Clone();
Response.Write(sc.MessageModel.Message + "<br />");
Response.Write(sc2.MessageModel.Message + "<br />");
// 修改原物件,淺層複製的副本也會受影響
sc.MessageModel.Message = "ShallowCopyShallowCopy";
Response.Write(sc.MessageModel.Message + "<br />");
Response.Write(sc2.MessageModel.Message + "<br />");
}
private void ShowDeepCopy()
{
var dc = new DeepCopy { MessageModel = new MessageModel("DeepCopy", DateTime.Now) };
var dc2 = (DeepCopy)dc.Clone();
Response.Write(dc.MessageModel.Message + "<br />");
Response.Write(dc2.MessageModel.Message + "<br />");
// 修改原物件,深層複製的副本不受影響
dc.MessageModel.Message = "DeepCopyDeepCopy";
Response.Write(dc.MessageModel.Message + "<br />");
Response.Write(dc2.MessageModel.Message + "<br />");
}
}
ShallowCopy
ShallowCopy
ShallowCopyShallowCopy
ShallowCopyShallowCopy <-- 副本也被修改了
DeepCopy
DeepCopy
DeepCopyDeepCopy
DeepCopy <-- 副本保持原狀
| 特性 | 淺層複製 | 深層複製 |
|---|---|---|
| 實作方式 | MemberwiseClone() |
手動 new 參考類型物件 |
| 參考類型行為 | 共用同一記憶體位址 | 獨立記憶體空間 |
| 效能 | 較快 | 較慢 (需遞迴複製) |
| 適用場景 | 物件僅含值類型或可共享參考 | 物件包含需獨立修改的參考類型 |
原型模式在 C# 中透過 ICloneable 介面輕鬆實作。選擇淺層或深層複製取決於業務需求:若複製後的物件不需獨立修改巢狀物件,淺層複製效能較佳;反之,深層複製能確保物件圖的完全隔離。實務上也可考慮序列化反序列化 (如 JSON、Binary) 來達成通用的深層複製。