可以看到,客户程序通过注册原型实例就可以将一个具体产品类并入到系统中,在运行时刻,可以动态的建立和删除原型。最后还要注意一点,在上面的例子中,用的是浅表复制。如果想做深复制,需要通过序列化的方式来实现。经过了上面的分析之后,我们再来思考下面的问题:
1.为什么需要Prototype模式?
引入原型模式的本质在于利用已有的一个原型对象,快速的生成和原型对象一样的实例。你有一个A的实例a:A a = new A();现在你想生成和car1一样的一个实例b,按照原型模式,应该是这样:A b = a.Clone();而不是重新再new一个A对象。通过上面这句话就可以得到一个和a一样的实例,确切的说,应该是它们的数据成员是一样的。Prototype模式同样是返回了一个A对象而没有使用new操作。
2.引入Prototype模式带来了什么好处?
可以看到,引入Prototype模式后我们不再需要一个与具体产品等级结构平行的工厂方法类,减少了类的构造,同时客户程序可以在运行时刻建立和删除原型。
3.Prototype模式满足了哪些面向对象的设计原则?
依赖倒置原则:上面的例子,原型管理器(ColorManager)仅仅依赖于抽象部分(ColorPrototype),而具体实现细节(ConcteteColorPrototype)则依赖与抽象部分(ColorPrototype),所以Prototype很好的满足了依赖倒置原则。

通过序列化实现深拷贝
要实现深拷贝,可以通过序列化的方式。抽象类及具体类都必须标注为可序列化的[Serializable],上面的例子加上深拷贝之后的完整程序如下:
using System;
![]()
using System.Collections;
![]()
using System.IO;
![]()
using System.Runtime.Serialization;
![]()
using System.Runtime.Serialization.Formatters.Binary;
![]()
![]()
[Serializable]
![]()
abstract class ColorPrototype
![]()
{
![]()
public abstract ColorPrototype Clone(bool Deep);
![]()
}
![]()
![]()
[Serializable]
![]()
class ConcteteColorPrototype : ColorPrototype
![]()
{
![]()
![]()
private int _red, _green, _blue;
![]()
![]()
![]()
public ConcteteColorPrototype(int red, int green, int blue)
![]()
{
![]()
this._red = red;
![]()
this._green = green;
![]()
this._blue = blue;
![]()
}
![]()
public override ColorPrototype Clone(bool Deep)
![]()
{
![]()
if(Deep)
![]()
return CreateDeepCopy();
![]()
else
![]()
return (ColorPrototype) this.MemberwiseClone();
![]()
}
![]()
![]()
//实现深拷贝
![]()
public ColorPrototype CreateDeepCopy()
![]()
{
![]()
ColorPrototype colorPrototype;
![]()
![]()
MemoryStream memoryStream = new MemoryStream();
![]()
BinaryFormatter formatter = new BinaryFormatter();
![]()
![]()
formatter.Serialize(memoryStream, this);
![]()
memoryStream.Position = 0;
![]()
![]()
colorPrototype = (ColorPrototype)formatter.Deserialize(memoryStream);
![]()
return colorPrototype;
![]()
}
![]()
![]()
public ConcteteColorPrototype Create(int red,int green,int blue)
![]()
{
![]()
return new ConcteteColorPrototype(red,green,blue);
![]()
}
![]()
![]()
public void Display(string _colorname)
![]()
{
![]()
Console.WriteLine("{0}'s RGB Values are: {1},{2},{3}",
![]()
_colorname,_red, _green, _blue );
![]()
}
![]()
}
![]()
![]()
class ColorManager
![]()
{
![]()
Hashtable colors = new Hashtable();
![]()
public ColorPrototype this[string name]
![]()
{
![]()
get
![]()
{
![]()
return (ColorPrototype)colors[name];
![]()
}
![]()
set
![]()
{
![]()
colors.Add(name,value);
![]()
}
![]()
}
![]()
}
![]()
![]()
![]()
class App
![]()
{
![]()
public static void Main(string[] args)
![]()
{
![]()
ColorManager colormanager = new ColorManager();
![]()
![]()
//初始化颜色
![]()
colormanager["red"] = new ConcteteColorPrototype(255, 0, 0);
![]()
colormanager["green"] = new ConcteteColorPrototype(0, 255, 0);
![]()
colormanager["blue"] = new ConcteteColorPrototype(0, 0, 255);
![]()
colormanager["angry"] = new ConcteteColorPrototype(255, 54, 0);
![]()
colormanager["peace"] = new ConcteteColorPrototype(128, 211, 128);
![]()
colormanager["flame"] = new ConcteteColorPrototype(211, 34, 20);
![]()
![]()
//使用颜色
![]()
string colorName = "red";
![]()
ConcteteColorPrototype c1 = (ConcteteColorPrototype)colormanager[colorName].Clone(false);
![]()
c1.Display(colorName);
![]()
![]()
colorName = "peace";
![]()
ConcteteColorPrototype c2 = (ConcteteColorPrototype)colormanager[colorName].Clone(true);
![]()
c2.Display(colorName);
![]()
![]()
colorName = "flame";
![]()
ConcteteColorPrototype c3 = (ConcteteColorPrototype)colormanager[colorName].Clone(true);
![]()
c3.Display(colorName);
![]()
![]()
Console.ReadLine();
![]()
}
![]()
}
![]()