初尝Prototype 设计模式
我们从图书馆发现期刊上有感兴趣的文章,不能直接在书上做记号。这个时候,可以找到管理员将他们影印成一份自己的拷贝,然后就可以尽情的干嘛了。Prototype 设计模式的作用与此类似,在父类中定义了一个抽象的clone方法,然后在子类中得到应有的重写。在客户端代码使用子类时,为了不破坏系统中的数据,则可以获取其克隆后的副本。被设计成Prototype 的事物应该和车展上的汽车一样,你看中要购买的是该款车型,而你付款后得到的应该是同款车型的副本(不是展台上的那辆)。
意图
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
结构
假定我们要开发一个调色板。直接使用OO的观念,抽象出一个Color 类,然后每一种颜色的创建都对应一个工厂类。虽然封装了对new 的依赖,但在类的数量这个维度,则显得很无力。这个时候,我们来看看原型设计模式的代码:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
namespace Prototype
{
[Serializable]
public abstract class ColorPrototype
{
public abstract ColorPrototype clone(bool isDeep);
}
[Serializable]
public class Color : ColorPrototype
{
private int _red;
public int Red
{
get { return _red; }
set { _red = value; }
}
private int _green;
public int Green
{
get { return _green; }
set { _green = value; }
}
private int _blue;
public int Blue
{
get { return _blue; }
set { _blue = value; }
}
public Color(int red,int green,int blue)
{
this._red = red;
this._blue = blue;
this._green = green;
}
//如果深度拷贝的话,则进行序列化和反序列化的操作
public override ColorPrototype clone(bool isDeep)
{
if (!isDeep)
return (ColorPrototype)this.MemberwiseClone();
else {
ColorPrototype colorPrototype;
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms,this);
ms.Position = 0;
colorPrototype = (ColorPrototype)bf.Deserialize(ms);
return colorPrototype;
}
}
public void Draw(string name) {
Console.WriteLine("{0}'s RGB value :{1},{2},{3}.",name,_red,_green,_blue);
}
}
public class ColorTool
{
Hashtable table = new Hashtable();
public Color this[string name] {
get {
return (Color)table[name];
}
set {
if (!table.Contains(name))
table.Add(name, value);
else
table[name] = value;
}
}
}
class Program
{
static void Main(string[] args)
{
//初始化颜色
ColorTool ct = new ColorTool();
ct["Red"] = new Color(255, 0, 0);
ct["Green"] = new Color(0, 255, 0);
ct["Blue"] = new Color(0, 0, 255);
ct["Green"] = new Color(0, 255, 1);
//使用颜色
string colorName = "Red";
Color red = (Color)ct[colorName].clone(true);
red.Draw(colorName);
colorName = "Green";
Color green=(Color)ct[colorName].clone(false);
green.Draw(colorName);
//若不克隆,则污染了ColorTool中的Blue。
colorName="Blue";
Color blue = ct[colorName];
blue.Blue = 1;
//blue.Draw(colorName);
ct[colorName].Draw(colorName);
}
}
}
首先从子类的数目上大大减少了,不需要再为每一种具体的颜色产品而定一个类和与它等级平行的工厂方法类,而ColorTool则扮演了原型管理器的角色。
使用效果:
- 它对客户隐藏了具体的产品类,因此减少了客户知道的名字的数目。
- Prototype模式允许客户只通过注册原型实例就可以将一个具体产品类并入到系统中,客户可以在运行时刻建立和删除原型。
- 减少了子类构造,Prototype模式是克隆一个原型而不是请求工厂方法创建一个,所以它不需要一个与具体产品类平行的Creater类层次。
- Portotype模式具有给一个应用软件动态加载新功能的能力。由于Prototype的独立性较高,可以很容易动态加载新功能而不影响老系统。
- 产品类不需要非得有任何事先确定的等级结构,因为Prototype模式适用于任何的等级结构
- Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。


近期评论