一、引言
在軟件系統中,當創建一個類的實例的過程很昂貴或很複雜,並且我們需要創建多個這樣類的實例時,如果我們用new操作符去創建這樣的類實例,這未免會增加創建類的複雜度和耗費更多的內存空間,因爲這樣在內存中分配了多個一樣的類實例對象,然後如果採用工廠模式來創建這樣的系統的話,隨着產品類的不斷增加,導致子類的數量不斷增多,反而增加了系統複雜程度,所以在這裏使用工廠模式來封裝類創建過程並不合適,然而原型模式可以很好地解決這個問題,因爲每個類實例都是相同的,當我們需要多個相同的類實例時,沒必要每次都使用new運算符去創建相同的類實例對象,此時我們一般思路就是想——只創建一個類實例對象,如果後面需要更多這樣的實例,可以通過對原來對象拷貝一份來完成創建,這樣在內存中不需要創建多個相同的類實例,從而減少內存的消耗和達到類實例的複用。然而這個思路正是原型模式的實現方式。下面就具體介紹下設計模式中的原型設計模式。
二、原型模式類圖
下面看下原型模式的類圖,通過類圖來理清原型模式實現中類之間的關係。具體類圖如下:
三、原型模式的詳細介紹
在現實生活中,也有很多原型設計模式的例子,例如,細胞分裂的過程,一個細胞的有絲分裂產生兩個相同的細胞;還有西遊記中孫悟空變出後孫的本領和火影忍者中鳴人的隱分身忍術等。下面就以孫悟空爲例子來演示下原型模式的實現。具體的實現代碼如下:
參考程序:
using UnityEngine;
using System.Collections;
/// <summary>
/// 孫悟空原型
/// </summary>
public abstract class MonkeyKingPrototype
{
public string Id { get; set; }
public MonkeyKingPrototype(string id)
{
this.Id = id;
}
// 克隆方法,即孫大聖說“變”
public abstract MonkeyKingPrototype Clone();
}
/// <summary>
/// 創建具體原型
/// </summary>
public class ConcretePrototype : MonkeyKingPrototype
{
//構造函數加上 base(id) 就是說子類裏的 id 和父類的 id 是一回事兒,先調用父類的構造函數,然後才輪到子類的。
public ConcretePrototype(string id)
: base(id)
{ }
/// <summary>
/// 淺拷貝
/// </summary>
/// <returns></returns>
public override MonkeyKingPrototype Clone()
{
// 調用MemberwiseClone方法實現的是淺拷貝,另外還有深拷貝
return (MonkeyKingPrototype)this.MemberwiseClone();
}
}
客戶端代碼:
using UnityEngine;
using System.Collections;
public class PrototypePatternInstance : MonoBehaviour {
void Start ()
{
// 孫悟空 原型
MonkeyKingPrototype prototypeMonkeyKing = new ConcretePrototype("MonkeyKing");
// 變一個
MonkeyKingPrototype cloneMonkeyKing = prototypeMonkeyKing.Clone() as ConcretePrototype;
Debug.Log("Cloned1:\t"+cloneMonkeyKing.Id);
// 變兩個
MonkeyKingPrototype cloneMonkeyKing2 = prototypeMonkeyKing.Clone() as ConcretePrototype;
Debug.Log("Cloned2:\t" + cloneMonkeyKing2.Id);
}
}
上面代碼實現的淺拷貝的方式,淺拷貝是指當對象的字段值被拷貝時,字段引用的對象不會被拷貝。例如,如果一個對象有一個指向字符串的字段,並且我們對該對象做了一個淺拷貝,那麼這兩個對象將引用同一個字符串,而深拷貝是對對象實例中字段引用的對象也進行拷貝,如果一個對象有一個指向字符串的字段,並且我們對該對象進行了深拷貝的話,那麼我們將創建一個對象和一個新的字符串,新的對象將引用新的字符串。也就是說,執行深拷貝創建的新對象和原來對象不會共享任何東西,改變一個對象對另外一個對象沒有任何影響,而執行淺拷貝創建的新對象與原來對象共享成員,改變一個對象,另外一個對象的成員也會改變。
四、原型模式的優缺點
原型模式的優點有:
原型模式向客戶隱藏了創建新實例的複雜性
原型模式允許動態增加或較少產品類。
原型模式簡化了實例的創建結構,工廠方法模式需要有一個與產品類等級結構相同的等級結構,而原型模式不需要這樣。
產品類不需要事先確定產品的等級結構,因爲原型模式適用於任何的等級結構
原型模式的缺點有:
每個類必須配備一個克隆方法
配備克隆方法需要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不一定很容易,特別當一個類引用不支持串行化的間接對象,或者引用含有循環結構的時候。