用原型執行個體指定建立對象的種類,並且通過拷貝這個原型來建立新的對象。
以.NET Framework 2.0 System.Collections中類為例
System.Collections. ICollection
public interface ICollection : IEnumerable
{
//
}
System.Collections. ICloneable
public interface ICloneable
{
object Clone();
}
System.Collections. Stack
Code
public class Stack : ICollection, ICloneable
{
//
public virtual Object Clone()
{
Stack s = new Stack(_size);
s._size = _size;
Array.Copy(_array, 0, s._array, 0, _size);
s._version = _version;
return s;
}
//
}
System.Collections. Queue
Code
public class Queue : ICollection, ICloneable
{
//
public virtual Object Clone()
{
Queue q = new Queue(_size);
q._size = _size;
int numToCopy = _size;
int firstPart = (_array.Length - _head < numToCopy) ? _array.Length - _head : numToCopy;
Array.Copy(_array, _head, q._array, 0, firstPart);
numToCopy -= firstPart;
if (numToCopy > 0)
Array.Copy(_array, 0, q._array, _array.Length - _head, numToCopy);
q._version = _version;
return q;
}
//
}
調用代碼
Code
public class Client
{
public static void Main()
{
Stack myStack = new Stack();
myStack.Push("Hello");
myStack.Push("World");
myStack.Push("!");
Stack myStackCopy = (Stack)myStack.Clone();
foreach (string s in myStackCopy)
{
Console.Write(s);
}
Console.WriteLine();
Console.ReadLine();
}
}
在.NET Framework中,可以通過實現ICloneable介面來實現原型模式,ICloneable介面只有一個Clone方法。複製的實現方法有兩種:淺拷貝(shallow copy)與深拷貝(deep copy)。
淺拷貝是指當對象的欄位值被拷貝時,欄位引用的對象不會被拷貝。例如,如果一個對象有一個指向字串的欄位,並且我們對該對象做了一個淺拷貝,那麼兩個對象將引用同一個字串。而深拷貝是對對象執行個體中欄位引用的對象也進行拷貝的一種方式,所以如果一個對象有一個指向字串的欄位,並且我們對該對象做了一個深拷貝的話,我們將建立一個新的對象和一個新的字串--新對象將引用新字串。需要注意的是執行深拷貝後,原來的對象和新建立的對象不會共用任何東西;改變一個對象對另外一個對象沒有任何影響。
對於實值型別,淺拷貝通過賦值等操作直接實現,將對象中的實值型別的欄位拷貝到新的對象中;深拷貝和淺拷貝相同,通過賦值等操作直接實現,將對象中的實值型別的欄位拷貝到新的對象中。 對於參考型別,淺拷貝通過MemberwiseClone 方法建立一個淺副本,方法是建立一個新對象,如果欄位是實值型別的,則對該欄位執行逐位複製,如果欄位是參考型別,則複製引用原始對象,與原對象引用同一對象;深拷貝拷貝對象應用,也拷貝對象實際內容,也就是建立了一個新的對象,改變新對象不會影響到原始對象的內容。
在下列情況下,應當使用Prototype模式:
1.當一個系統應該獨立於它的產品建立,構成和表示時;
2.當要執行個體化的類是在運行時刻指定時,例如,通過動態裝載;
3.為了避免建立一個與產品類層次平行的工廠類層次時;
4.當一個類的執行個體只能有幾個不同狀態組合中的一種時。建立相應數目的原型並複製它們可能比每次用合適的狀態手工執行個體化該類更方便一些。